Guest User

zerojudge a021

a guest
May 10th, 2024
1,750
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.68 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <string>
  4.  
  5. // 若num1<num2,sign則會為true,反之為false。
  6. bool compare(const std::string &num1, const std::string &num2) {
  7.     if (num1.length() > num2.length()) {
  8.         return false;
  9.     }
  10.     else if (num1.length() < num2.length()) {
  11.         return true;
  12.     }
  13.     else {
  14.         for (int i = 0; i < num1.length(); ++i) { // 若是num1和num2長度相同則一一比較每個bit的值
  15.             if (num1[i] < num2[i]) {
  16.                 return true;
  17.             }
  18.             else if (num1[i] > num2[i]) {
  19.                 return false;
  20.             }
  21.         }
  22.     }
  23.     return false; // num1 == num2的話就會到這邊,把sign設為false代表相減不為負
  24. }
  25.  
  26. // 加法
  27. std::string add(std::string num1, std::string num2) {
  28.     if (compare(num1, num2)) // 比較num1和num2大小,讓num1>=num2,方便後面計算
  29.         std::swap(num1, num2);
  30.     int index1 = num1.length(), index2 = num2.length(), carry = 0; // carry代表進位,bit相加結果>9為1,反之carry為0
  31.     std::string ans = "";
  32.  
  33.     while (index1 > 0 || index2 > 0) { // num1和num1都從尾端開始相加
  34.         --index1, --index2;
  35.         int n = num1[index1] - '0' + carry;
  36.         if (index2 > -1) { // 由於在while()前呼叫compare()和std::swap,因此num1必>=num2,若num2加完了就不再加
  37.             n += num2[index2] - '0';
  38.         }
  39.         carry = n / 10;
  40.         n %= 10;
  41.         ans += (n + '0');
  42.     }
  43.     if (carry > 0) // 處理 999 + 1 = "1"000 這種進位問題
  44.         ans += '1';
  45.  
  46.     reverse(ans.begin(), ans.end()); // ans是最小bit先存入,所以答案要反序輸出
  47.     return ans;
  48. }
  49.  
  50. // 減法
  51. std::string sub(std::string num1, std::string num2) {
  52.     bool is_negative = compare(num1, num2); // 用以判斷相減是否為負
  53.     if (is_negative)                        // 比較num1和num2大小,讓num1>=num2,方便後面計算
  54.         std::swap(num1, num2);
  55.     int index1 = num1.length(), index2 = num2.length(), carry = 0; // carry代表進位,bit相減結果<0為-1,反之carry為0
  56.     std::string ans = "";
  57.  
  58.     while (index1 > 0 || index2 > 0) { // num1和num1都從尾端開始相減
  59.         --index1, --index2;
  60.         int n = num1[index1] - '0' + carry;
  61.         if (index2 > -1) { // 由於在while()前呼叫compare()和std::swap,因此num1必>=num2,若num2減完了就不再減
  62.             n -= num2[index2] - '0';
  63.         }
  64.         if (n < 0) { // 當前bit相減為負,要向前借位
  65.             carry = -1;
  66.             n += 10;
  67.         }
  68.         else {
  69.             carry = 0; // 當前bit相減為正,不用借位
  70.         }
  71.         ans += (n + '0');
  72.     }
  73.     reverse(ans.begin(), ans.end());         // ans是最小bit先存入,所以答案要反序輸出
  74.     for (int i = 0; i < ans.length(); ++i) { // 處理開頭的0,像是00021354要變成21354
  75.         if (ans[i] != '0') {                 // 遇到不為0時,把前面的0全消除掉
  76.             ans.erase(0, i);
  77.             break;
  78.         }
  79.         else if (i == ans.length() - 1) // 若全部為0則輸出單個0,像是000000000要輸出0
  80.             return "0";
  81.     }
  82.     if (is_negative) // 原本的num1-num2為負數,開頭加個負號
  83.         ans = '-' + ans;
  84.     return ans;
  85. }
  86.  
  87. // 乘法,用長乘法計算,以多次呼叫add()完成
  88. std::string mul(std::string num1, std::string num2) {
  89.     std::string ans = "";
  90.     for (int i = num2.length() - 1; i > -1; --i) { // 從除數(num2)的最後一bit開始,
  91.         for (int j = 0; j < num2[i] - '0'; ++j) {  // 累加num2[i]次num1
  92.             // 由於每次進入add()都會呼叫compare()和std::swap(),讓add()中的num1>=num2,為了不讓mul()中的num1被更改值,所以用temp來代替num1進入add()
  93.             std::string temp = num1;
  94.             ans = add(ans, temp);
  95.         }
  96.         num1 += "0"; // 每做完一輪相加後,被乘數要往左1bit,也就是乘以10
  97.     }
  98.     return ans; // 由於是透過多次呼叫add()來完成長乘法,add()返回的string已經有reverse了,所以這邊可以直接輸出ans
  99. }
  100.  
  101. // 除法,用長除法計算,以多次呼叫sub()完成
  102. std::string div(std::string num1, std::string num2) {
  103.     if (compare(num1, num2)) // 若輸入的num1<num2直接return 0
  104.         return "0";
  105.     // index用以計算num1的index,假設num1 = 1234,num2 = 11,一開始now = "",index = 0,
  106.     // 接下來now累加num1[index]變成1,index + 1,拿去和num2比較,若比num2小則繼續累加num1[index],
  107.     // 此時now = 12,拿去後num2比較,傳回來的sign為false代表num1>=num2,就可以進行相減,12 - 11 = 1
  108.     // ,now = 1,這時ans_count + 1,再拿now = 1去和num2 = 11比較,發現比除數小,因此把ans_count放
  109.     // 入ans中,然後now累加num1[index],以此一直重複到num1被累加完所有bit。
  110.     int index = 0, ans_count = 0; // index是num1的index,一開始為0,隨著每次分配最左邊的bit給now,index會加1
  111.     std::string ans = "", now = "";
  112.     while (true) {
  113.         if (compare(now, num2)) { // 進行比較,若sign為true代表now(被除數) < num2(除數),要累加1個num1最左邊的bit給now
  114.             ans += ans_count + '0'; // 把上次相減的次數(也就是商)加進ans中,由於一開始now為"",所以會有數個0開頭
  115.             ans_count = 0;          // 重置ans_count
  116.             if (index == num1.length()) // 若num1的bit都被累加完,則跳出while迴圈
  117.                 break;
  118.             now += num1[index]; // 讓now累加num1最左邊的bit
  119.             ++index;            // 累加後num1的index往右移
  120.         }
  121.         else {
  122.             ++ans_count;          // 每次相減後都加1
  123.             now = sub(now, num2); // now = 相減後的結果
  124.             if (now == "0")       // 若是相減剛好為0,則把now設為""
  125.                 now = "";
  126.         }
  127.     }
  128.     for (int i = 0; i < ans.length(); ++i) { // 消除開頭的0,例如:000123要變成123
  129.         if (ans[i] != '0') {
  130.             ans.erase(0, i);
  131.             break;
  132.         }
  133.     }
  134.     return ans; // 由於是透過多次呼叫sub()來完成長乘法,sub()返回的string已經有reverse了,所以這邊可以直接輸出ans
  135. }
  136.  
  137. int main() {
  138.     char op;
  139.     std::string num1, num2;
  140.     while (std::cin >> num1 >> op >> num2) {
  141.         if (op == '+')
  142.             std::cout << add(num1, num2) << '\n';
  143.         else if (op == '-')
  144.             std::cout << sub(num1, num2) << '\n';
  145.         else if (op == '*')
  146.             std::cout << mul(num1, num2) << '\n';
  147.         else if (op == '/')
  148.             std::cout << div(num1, num2) << '\n';
  149.     }
  150.     return 0;
  151. }
Advertisement
Add Comment
Please, Sign In to add comment