-
big_integer_operation(큰 정수 연산)Number Theory 2017. 3. 20. 22:47
int 보다 큰 범위의 정수들을 기본연산해주는 함수들이다. (음수 연산 가능)
기본 원리는 int 연산과 같다. 그러나 int는 32개의 bit라면 이 big_int는 32 * size 개의 bit이다.
size가 1000이라면 약 자릿수 10000자리정도까지 계산 가능하다.
main 함수에 적혀있는 것은 fibonacci 수열의 10만항을 구하도록 예제를 적어놓았다.
size가 클 수록 연산의 속도가 눈에 띄게 감소한다.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471#include <stdio.h>#include <stdlib.h>#define size 5000typedef struct{unsigned int d[size];}big_int;//big_int를 생성해 주는 함수big_int* generate_big_int();//big_int를 지워주는 함수. 메모리 반환void delete_big_int(big_int *a);//big_int를init 값으로 초기화 시켜준다.void init_big_int(big_int* a, int init);//big_int를 입력받는 함수 a에 입력시킨다.void input_big_int(big_int* a);//big_int를 출력해주는 함수void print_big_int(big_int *a);//big_int 왼쪽으로 shift 시켜주는함수void lshift_big_int(big_int *a);//big_int 오른쪽으로 shift 시켜주는 함수.void rshift_big_int(big_int *a);//big_int를 2의 보수화 해주는 함수void complement_big_int(big_int *a);//big_int a값을 b에다 옮겨주는 함수. 즉 b = a;void assign_big_int(big_int *a, big_int *b);//c = a + bvoid add_big_int(big_int *a, big_int *b, big_int *c);//c = a - bvoid sub_big_int(big_int *a, big_int *b, big_int *c);//c = a * bvoid mul_big_int(big_int *a, big_int *b, big_int *c);//a와b 값이 unsigned라고 했을 때 둘을 비교해주는 함수.int cmp_unsigned_big_int(big_int *a, big_int *b);//a와 b 값이 signed 라고 했을 때 둘을 비교해주는 함수.int cmp_signed_big_int(big_int *a, big_int *b);//c = a / bvoid div_big_int(big_int *a, big_int *b, big_int *c);//c = a % bvoid mod_big_int(big_int *a, big_int *b, big_int *c);int main(){big_int *a, *b, *c;int i;a = generate_big_int();b = generate_big_int();c = generate_big_int();init_big_int(a, 0);init_big_int(b, 1);for (i = 0; i < 100000; i++){add_big_int(a, b, c);assign_big_int(b, a);assign_big_int(c, b);}print_big_int(c);printf("\n");delete_big_int(a);delete_big_int(b);return 0;}big_int* generate_big_int(){int i;big_int *a = (big_int*)malloc(sizeof(big_int));for (i = 0; i < size; i++)a->d[i] = 0;return a;}void delete_big_int(big_int *a){free(a);}void init_big_int(big_int* a, int init){int sign = init & 0x80000000;int i;if (sign)sign = 0x77777777;elsesign = 0x00000000;for (i = 0; i < size - 1; i++)a->d[i] = sign;a->d[i] = init;}void input_big_int(big_int* a){char *buffer;int i,j,k;int n = 0;int sign = 0;int carry = 0;buffer = (char*)malloc(sizeof(char)* 10 * size + 1);printf("please input integer : ");for (i = 0; i <= size * 10 && (buffer[i] = getchar()) != '\n'; i++) // buffer[i]에는'\n' 이 저장buffer[i] -= '0';if (buffer[0] == '-' - '0')sign = 1;k = sign;while (k != i){carry = 0;for (j = k; j < i; j++){buffer[j] = (carry + buffer[j]);if (buffer[j] % 2)carry = 10;elsecarry = 0;buffer[j] /= 2;}if (carry){a->d[size - 1 - n / 32] += 0x00000001 << (n%32);}n++;if (buffer[k] == 0)k++;}if (sign)complement_big_int(a);free(buffer);return;}void print_big_int(big_int *a){char *buffer;int sign = a->d[0] & 0x80000000;int i,j,k;int n=1; //n은 숫자열 크기int carry;buffer = (char*)malloc(sizeof(char)* 10 * size + 1);buffer[0] = 0;if (sign){printf("-");complement_big_int(a);}for (i = 0; i < size; i++){for (j = 0; j < 32; j++){carry = 0;for (k = 0; k <n ; k++){buffer[k] = buffer[k] * 2 + carry;carry = buffer[k] / 10;buffer[k] = buffer[k] % 10;}if (carry)buffer[n++] = 1;if (a->d[i] & (0x80000000 >> j))buffer[0]++;}}for (i = n - 1; i >= 0; i--)printf("%c", buffer[i] + '0');if (sign)complement_big_int(a);free(buffer);}void lshift_big_int(big_int *a){int i;int carry = 0;int temp;for (i = size - 1; i >= 0; i--){temp = carry;if (a->d[i] & 0x80000000)carry = 1;elsecarry = 0;a->d[i] = a->d[i] << 1;a->d[i] += temp;}}void rshift_big_int(big_int *a){int i;int carry = 0;int temp;for (i = 0; i <size; i++){temp = carry;if (a->d[i] & 0x00000001)carry = 0x80000000;elsecarry = 0x00000000;a->d[i] = a->d[i] >> 1;a->d[i] += temp;}}void complement_big_int(big_int *a){int i,j;for (i = 0; i < size; i++)a->d[i] = ~a->d[i];for (i = size - 1; i >= 0; i--){for (j = 0; j < 32; j++){if (a->d[i] & (0x00000001 << j)){a->d[i] = a->d[i] - (0x00000001 << j);}else{a->d[i] = a->d[i] + (0x00000001 << j);return;}}}}void assign_big_int(big_int *a, big_int *b){for (int i = 0; i < size; i++)b->d[i] = a->d[i];}void add_big_int(big_int *a, big_int *b, big_int *c){int i;int carry = 0;unsigned long long temp;for (i = size - 1; i >= 0;i--){temp = (unsigned long long)a->d[i] + (unsigned long long)b->d[i] + carry;if (temp >= 0x0000000100000000)carry = 1;elsecarry = 0;c->d[i] = (unsigned int)temp;}}void sub_big_int(big_int *a, big_int *b, big_int *c){int i;unsigned long long borrow = 0;for (i = size - 1; i >= 0; i--){if ((unsigned long long)a->d[i] >= (unsigned long long)b->d[i] + borrow){c->d[i] = a->d[i] - b->d[i]- borrow;borrow = 0;}else{c->d[i] = a->d[i] - b->d[i] - borrow;borrow = 1;}}}void mul_big_int(big_int *a, big_int *b, big_int *c){big_int *temp_a, *temp_b;int i, j,k;unsigned long long temp;unsigned long long carry;temp_a = generate_big_int();temp_b = generate_big_int();assign_big_int(a, temp_a);assign_big_int(b, temp_b);for (i = size - 1; i >= 0; i--)c->d[i] = 0;for (i = size - 1; i >= 0; i--){carry = 0;for (j = size - 1,k = i ; j >= 0 && k>=0; j--,k--){temp = (unsigned long long)temp_a->d[j] * (unsigned long long)temp_b->d[i] + (unsigned long long)c->d[k] + carry;c->d[k] = (unsigned int)temp;carry = temp >> 32;}}delete_big_int(temp_a);delete_big_int(temp_b);}int cmp_unsigned_big_int(big_int *a, big_int *b){int i;for (i = 0; i < size; i++){if (a->d[i] > b->d[i])return 1;if (a->d[i] < b->d[i])return -1;}return 0;}int cmp_signed_big_int(big_int *a, big_int *b){int i;if (!(a->d[0] & 0x80000000) && (b->d[0] & 0x80000000))return 1;else if ((a->d[0] & 0x80000000) && !(b->d[0] & 0x80000000))return -1;else if (!(a->d[0] & 0x80000000) && !(b->d[0] & 0x80000000)){for (i = 0; i < size; i++){if (a->d[i] > b->d[i])return 1;if (a->d[i] < b->d[i])return -1;}}else{for (i = 0; i < size; i++){if (a->d[i] > b->d[i])return -1;if (a->d[i] < b->d[i])return 1;}}return 0;}void div_big_int(big_int *a, big_int *b, big_int *c){big_int *temp_a, *temp_b;int a_sign = a->d[0] & 0x80000000;int b_sign = b->d[0] & 0x80000000;int i;temp_a = generate_big_int();temp_b = generate_big_int();assign_big_int(a, temp_a);assign_big_int(b, temp_b);for (i = size - 1; i >= 0; i--)c->d[i] = 0;if (a_sign)complement_big_int(temp_a);if (b_sign)complement_big_int(temp_b);i = 0;while (!(temp_b->d[0] & 0x80000000)){lshift_big_int(temp_b);i++;}for (; i >= 0; i--){if (cmp_unsigned_big_int(temp_a, temp_b) >= 0){c->d[size - 1 - i / 32] = c->d[size - 1 - i / 32] + (0x00000001 << (i % 32));sub_big_int(temp_a, temp_b, temp_a);}rshift_big_int(temp_b);}if (a_sign ^ b_sign)complement_big_int(c);delete_big_int(temp_a);delete_big_int(temp_b);}void mod_big_int(big_int *a, big_int *b, big_int *c){big_int *temp_a, *temp_b;int a_sign = a->d[0] & 0x80000000;int b_sign = b->d[0] & 0x80000000;int i;temp_a = generate_big_int();temp_b = generate_big_int();assign_big_int(a, temp_a);assign_big_int(b, temp_b);for (i = size - 1; i >= 0; i--)c->d[i] = 0;if (a_sign)complement_big_int(temp_a);if (b_sign)complement_big_int(temp_b);i = 0;while (!(temp_b->d[0] & 0x80000000)){lshift_big_int(temp_b);i++;}for (; i >= 0; i--){if (cmp_unsigned_big_int(temp_a, temp_b) >= 0){c->d[size - 1 - i / 32] = c->d[size - 1 - i / 32] + (0x00000001 << (i % 32));sub_big_int(temp_a, temp_b, temp_a);}rshift_big_int(temp_b);}assign_big_int(temp_a, c);if (a_sign)complement_big_int(c);delete_big_int(temp_a);delete_big_int(temp_b);}'Number Theory' 카테고리의 다른 글
fibonacci 100000th (피보나치 수열 10만항) (0) 2017.03.20 NIM GAME (님 게임) (0) 2017.03.20 The Fibonacci number (피보나치 수) (0) 2017.02.01 The Mathematical Induction (수학적 귀납법) (0) 2017.01.03 Dirichlet Approximation Theorem (디리클레 근사) (0) 2016.12.20