忙里偷閑,終於完成了無限大整數相加算法的C語言代碼,無限大整數相加算法的算法分析在這里。
500位的加法運行1000次,不打印結果的情況下耗時0.036秒,打印結果的情況下耗時16.285秒。
下面是源碼:
#include <stdio.h> #include <stdlib.h> #include<string.h> #include <time.h> #define MAXNUM 1000000000000000000 /* 存儲數據用的結構 long int型指針(Number)指向一個long int 數組,索引值最底的位, 為10進制數的最低18位。依次類推。 int型數值(Length)為數組的長度。 因為數組長度受int型最大值的限制,所以這個算法也不能真正實現“無限”。 */ struct BigInt{ long long* Number; int Length; }; void PrintBigInt(BigInt* bigNumber); long long pow(int x, int y); BigInt* MakeBigIntFromString(char* bigIntString); void DeleteBigInt(BigInt* bigNumber); BigInt* Add2BigInt(BigInt* n1, BigInt* n2); void main(){ char* numberStr = "99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\0"; char* numberStr2 = "99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\0"; BigInt* bn = MakeBigIntFromString(numberStr); BigInt* bn2 = MakeBigIntFromString(numberStr2); double tstart, tend, tcost; tstart = clock(); PrintBigInt(bn); PrintBigInt(bn2); for (int i = 0; i < 1000; i++){ BigInt* result = Add2BigInt(bn, bn2); //PrintBigInt(result); DeleteBigInt(result); } DeleteBigInt(bn); DeleteBigInt(bn2); tend = clock(); tcost = (double)(tend - tstart) / CLOCKS_PER_SEC; printf("%lf\n", tcost); } BigInt* Add2BigInt(BigInt* n1, BigInt* n2){ int maxLength = n1->Length; if (maxLength < n2->Length){ maxLength = n2->Length; } /* 加法只可能產生1位的進位,所以,只需要創建一個和最大長度相同的。 */ BigInt* nOut = (BigInt*)malloc(sizeof(BigInt)); nOut->Length = maxLength; nOut->Number = (long long*)malloc(sizeof(long long)* nOut->Length); for (int i = 0; i < nOut->Length; i++){ nOut->Number[i] = 0; } for (int i = 0; i < nOut->Length; i++){ if (n1->Length > i){ nOut->Number[i] += n1->Number[i]; } if (n2->Length > i){ nOut->Number[i] += n2->Number[i]; } /* 處理進位。最高位不需要處理。 */ if (i != (nOut->Length - 1)){ if (nOut->Number[i] >= MAXNUM){ nOut->Number[i] -= MAXNUM; nOut->Number[i + 1] = 1; } } } return nOut; } /* 從高到低顯示數值 不考慮單個long long數據超出18位的情況。 */ void PrintBigInt(BigInt* bigNumber){ if (bigNumber == NULL){ return; } if (bigNumber->Length < 1){ return; } int length = bigNumber->Length - 1; for (int i = length; i >= 0; i--){ if (i != length){ if (bigNumber->Number[i] == 0){ printf("000000000000000000"); } else{ printf("%018lld", bigNumber->Number[i]); } } else{ if ((*bigNumber).Number[i] != 0){ printf("%lld", bigNumber->Number[i]); } } } printf("\n"); } /* 把字符串表示的數值格式化為BigInt型的結構 字符串結束位置用\0表示。 */ BigInt* MakeBigIntFromString(char* bigIntString){ /*獲取字符串長度*/ int cLength = strlen(bigIntString); BigInt* outBigInt = (BigInt*)malloc(sizeof(BigInt)); if (cLength % 18 != 0){ outBigInt->Length = cLength / 18 + 1; } else{ outBigInt->Length = cLength / 18; } if (outBigInt->Length == 0){ outBigInt->Length == 1; outBigInt->Number = (long long *)malloc(sizeof(long long)); outBigInt->Number[0] = 0; return outBigInt; } outBigInt->Number = (long long *)malloc(sizeof(long long)* outBigInt->Length); for (int i = 0; i < outBigInt->Length; i++){ outBigInt->Number[i] = 0; } int powNum = 0; int numPos = 0; for (int i = cLength - 1; i >= 0; i--){ powNum = (cLength - 1 - i) % 18; numPos = (cLength - 1 - i) / 18; outBigInt->Number[numPos] += (bigIntString[i] - 48) * pow(10, powNum); } return outBigInt; } /* 簡單的冪函數 x y 都必須為正整數 */ long long pow(int x, int y){ if (x == 0 || x < 0 || y < 0){ return 0; } if (x == 1 || y == 0){ return 1; } long long outNum = x; for (int i = 1; i < y; i++){ outNum = outNum * x; } return outNum; } void DeleteBigInt(BigInt* bigNumber){ if (bigNumber != NULL){ if (bigNumber->Number != NULL){ free(bigNumber->Number); } free(bigNumber); } }