高精度加法
阿新 • • 發佈:2020-07-19
吶!眾所周知,資料是有範圍的
\(Python \&\& Java:\) sorry,高精度真的可以為所欲為
本文為部落格園 ShyButHandsome的原創作品,轉載請註明出處
注:右邊有目錄,方便快速瀏覽
需求原因
C++
中的資料型別是有範圍的
實現思路
雖然內建資料類型範圍不大
但是字串能很長啊!
我們將加數的每一位都看作是一個字元的話
那我們就得到了兩個字串
程式碼實現
解釋都在程式碼裡了
#include <iostream> // EXIT_SUCCESS在stdlib庫中 #include <cstdlib> // strlen函式需要cstring庫 #include <cstring> using namespace std; // 500+6防止陣列越界 const int LENGTH_LIMIT = 5e2 + 6; // char表示的整數 減去一個‘0’就可以得到響應整數的ascii const int INT_CHANGER = '0'; // 個位數不能超過10 const int SINGLE_LIMIT = 10; char stringA[LENGTH_LIMIT]; char stringB[LENGTH_LIMIT]; int invertedA[LENGTH_LIMIT]; int invertedB[LENGTH_LIMIT]; int sum[LENGTH_LIMIT]; int main(void) { cin >> stringA >> stringB; // 倒序儲存 int lengthA = strlen(stringA); for (int i = 0; i < lengthA; i++) { // 由於strlen返回的長度是符合正常思維(從1開始) // 但我們是從0開始,所以要額外 - 1 invertedA[i] = stringA[lengthA - i - 1] - INT_CHANGER; } int lenghtB = strlen(stringB); for (int i = 0; i < lenghtB; i++) { invertedB[i] = stringB[lenghtB - i - 1] - INT_CHANGER; } // 和的最大長度是a,b最大值+1 const int MAX_LENGTH = ((lengthA < lenghtB) ? lenghtB : lengthA) + 1; // 進位 int carry = 0; // 模擬計算 for (int i = 0; i < MAX_LENGTH; i++) { // 對應位相加 sum[i] = invertedA[i] + invertedB[i] + carry; // 記錄下進位 carry = sum[i] / SINGLE_LIMIT; // 進位操作 sum[i] %= SINGLE_LIMIT; } // 這裡length選擇放在迴圈外,因為兩個迴圈都會用到它 // +1是因為strlen返回的陣列長度是從1開始計數的 int length = MAX_LENGTH; // 刪除前導零(確定數字實際長度) // 這裡取length>0,因為 // 如果刪到最後一位就必須得保留,不管它是不是0 for (length; length > 0; length--) { if (sum[length] == 0) { // 接著處理下一位 continue; } else { // 如果遇到一位非零就說明前導零刪乾淨了 // 接著刪就會刪去數字中的0了 break; } } // 正序輸出 for (length; length >= 0; length--) { cout << sum[length]; } // 額外輸出一個換行 cout << endl; // EXIT_SUCCESS means 0 return EXIT_SUCCESS; }
再給出一份用STL寫的:
#include <bits/stdc++.h> using namespace std; int main(void) { string strA, strB; cin >> strA >> strB; vector<int> numA, numB, sum; for (int i = strA.size() - 1; i >= 0; i--) { numA.push_back(strA[i] - '0'); } for (int i = strB.size() - 1; i >= 0; i--) { numB.push_back(strB[i] - '0'); } int carry = 0; for (int i = 0; i < (max(numA.size(), numB.size())); i++) { sum.push_back(carry); // If lenA != lenB sum[i] += (i > (numA.size() - 1) ? 0 : numA[i]) + (i > (numB.size() - 1) ? 0 : numB[i]); carry = (sum[i]) / 10; sum[i] %= 10; } if (carry != 0) { cout << carry; } for (int i = sum.size() - 1; i >= 0; i--) { cout << sum[i]; } cout << endl; return 0; }
易錯點
下面是我總結出的幾個易錯點
每個易錯點都給出了測試資料
可以利用右上角的複製按鈕快速複製
沒有處理進位
包括
- 每次沒有計算上次的進位啊
- 每次沒有加上上次的進位啊
- 邊界沒有進位啊
- 等等
測試資料:
輸入:
56546876443156448001
56453168410002134684
輸出:
113000044853158582685
刪除前導零錯誤
測試資料:
輸入 1:
11111111111111111111111111
9999999999999999999999999999999999
輸出 1:
10000000011111111111111111111111110
輸入 2:
0
0
輸出 2:
0
STL還要注意長度不一樣
輸入:
350204156568812004512541458715942878921069349854678
5120132301230048014584016540526804565814706519846494321001345794503242112976563432120
輸出:
5120132301230048014584016540526804916018863088658498833542804510446121034045913286798