挑战面试编程:大整数的加、减、乘、除
挑战面试编程:大整数的加、减、乘、除
一切都是有限的,哪怕是看起来无限的时间或空间都非常可能是有限的。在计算机中内置类型的加、减、乘、除都是有限的。我们来实现一个“无限”的大整数加、减、乘、除。
下面使用C++代码实现
#include <iostream> #include <string> using namespace std; //大整数的加减乘除 string add_int(string, string); string sub_int(string, string); string mul_int(string, string); string div_int(string, string); string mod_int(string, string); string divide_int(string, string, int); inline int compare(string s1, string s2) { if (s1.size() < s2.size()) return -1; else if (s1.size() > s2.size()) return 1; else return s1.compare(s2); } /* 大整数加法 本质上仅仅处理:两个正数相加,如 "123" + "234" 其他情况需转化 1. 正加负 => "123" + "-234" = "123" - "234" 转化为减法 2. 负加正 => "-234" + "123" = "123" - "234" 3. 负加负 => "-123" + "-234" = -("123" + "234") */ string add_int(string s1, string s2) { if (s1 == "0") return s2; if (s2 == "0") return s1; if (s1[0] == '-') { if (s2[0] == '-') { return "-" + add_int(s1.erase(0, 1), s2.erase(0, 1)); //情况三 } else { return sub_int(s2, s1.erase(0, 1)); //情况二 } } if (s2[0] == '-') { return sub_int(s1, s2.erase(0, 1)); //情况一 } //处理本质情况 string::size_type i, size1, size2; size1 = s1.size(); size2 = s2.size(); if (size1 < size2) { for (i = 0; i < size2 - size1; i++) //在s1左边补零 s1 = "0" + s1; } else { for (i = 0; i < size1 - size2; i++) //在s2左边补零 s2 = "0" + s2; } int n1, n2; n2 = 0; size1 = s1.size(); size2 = s2.size(); string res; for (i = size1 - 1; i != 0; i--) //从最低位加起 { n1 = (s1[i] - '0' + s2[i] - '0' + n2) % 10; //n1代表当前位的值 n2 = (s1[i] - '0' + s2[i] - '0' + n2) / 10; //n2代表进位 res = char(n1 + '0') + res; } /*上述循环不能处理第0位的原因在于i的类型是string::size_type,它是非负类型*/ //对于第0位单独处理 n1 = (s1[0] - '0' + s2[0] - '0' + n2) % 10; n2 = (s1[0] - '0' + s2[0] - '0' + n2) / 10; res = char(n1 + '0') + res; if (n2 == 1) res = "1" + res; return res; } /* 大整数减法 本质上仅仅处理:两整数相减,而且是一大减一小:"1234" - "234" 其他情况需转化 1. 小正减大正 => "234" - "1234" = -("1234" - "234") 2. 正减负 => "1234" - "-234" = "1234" + "234" 3. 负减正 => "-1234" - "234" = -("1234" + "234") 4. 负减负 => "-1234" - "-234" = "234" - "1234" = -("1234" - "234") */ string sub_int(string s1, string s2) { if (s2 == "0") return s1; if (s1 == "0") { if (s2[0] == '-') return s2.erase(0, 1); return "-" + s2; } if (s1[0] == '-') { if (s2[0] == '-') { return sub_int(s2.erase(0, 1), s1.erase(0, 1)); //情况四 } return "-" + add_int(s1.erase(0, 1), s2); //情况三 } if (s2[0] == '-') return add_int(s1, s2.erase(0, 1)); //情况二 //调整s1与s2的长度 string::size_type i, size1, size2; size1 = s1.size(); size2 = s2.size(); if (size1 < size2) { for (i = 0; i < size2 - size1; i++) //在s1左边补零 s1 = "0" + s1; } else { for (i = 0; i < size1 - size2; i++) //在s2左边补零 s2 = "0" + s2; } int t = s1.compare(s2); if (t < 0) //s1与s2的size同样。但 s1 < s2 return "-" + sub_int(s2, s1); if (t == 0) return "0"; //处理本质情况:s1 > s2 string res; string::size_type j; for (i = s1.size() - 1; i != 0; i--) { if (s1[i] < s2[i]) //不足,需向前借一位 { j = 1; while (s1[i - j] == '0') { s1[i - j] = '9'; j++; } s1[i - j] -= 1; res = char(s1[i] + ':' - s2[i]) + res; } else { res = char(s1[i] - s2[i] + '0') + res; } } res = char(s1[0] - s2[0] + '0') + res; //去掉前导零 res.erase(0, res.find_first_not_of('0')); return res; } string mul_int(string s1, string s2) { if (s1 == "0" || s2 == "0") return "0"; //sign是符号位 int sign = 1; if (s1[0] == '-') { sign *= -1; s1.erase(0, 1); } if (s2[0] == '-') { sign *= -1; s2.erase(0, 1); } string::size_type size1, size2; string res, temp; size1 = s1.size(); size2 = s2.size(); //让s1的长度最长 if (size1 < size2) { temp = s1; s1 = s2; s2 = temp; size1 = s1.size(); size2 = s2.size(); } int i, j, n1, n2, n3, t; for (i = size2 - 1; i >= 0; i--) { temp = ""; n1 = n2 = n3 = 0; for (j = 0; j < size2 - 1 - i; j++) temp = "0" + temp; n3 = s2[i] - '0'; for (j = size1 - 1; j >= 0; j--) { t = (n3*(s1[j] - '0') + n2); n1 = t % 10; //n1记录当前位置的值 n2 = t / 10; //n2记录进位的值 temp = char(n1 + '0') + temp; } if (n2) temp = char(n2 + '0') + temp; res = add_int(res, temp); } if (sign == -1) return "-" + res; return res; } string divide_int(string s1, string s2, int flag) //flag=1,返回商;flag=0,返回余数 { string quotient, residue; if (s2 == "0") { quotient = residue = "error"; if (flag == 1) return quotient; else return residue; } if (s1 == "0") { quotient = residue = "0"; if (flag == 1) return quotient; else return residue; } //sign1是商的符号,sign2是余数的符号 int sign1, sign2; sign1 = sign2 = 1; if (s1[0] == '-') { sign1 *= -1; sign2 = -1; s1.erase(0, 1); } if (s2[0] == '-') { sign1 *= -1; s2.erase(0, 1); } if (compare(s1, s2) < 0) { quotient = "0"; residue = s1; } else if (compare(s1, s2) == 0) { quotient = "1"; residue = "0"; } else { string temp; string::size_type size1, size2; size1 = s1.size(); size2 = s2.size(); int i; if (size2 > 1) temp.append(s1, 0, size2 - 1); for (i = size2 - 1; i < size1; i++) { temp = temp + s1[i]; //试商 for (char c = '9'; c >= '0' ; c--) { string t = mul_int(s2, string(1, c)); string s = sub_int(temp, t); if (s == "0" || s[0] != '-') { temp = s; quotient = quotient + c; break; } } } residue = temp; } //去除前导零 quotient.erase(0, quotient.find_first_not_of('0')); residue.erase(0, residue.find_first_not_of('0')); if (sign1 == -1) { quotient = "-" + quotient; } if (sign2 == -1) { if (residue.empty()) residue = "0"; else residue = "-" + residue; } if (flag == 1) return quotient; else return residue; } string div_int(string s1, string s2) { return divide_int(s1, s2, 1); } string mod_int(string s1, string s2) { return divide_int(s1, s2, 0); } int main(void) { string s1, s2; char op; while (cin >> s1 >> op >> s2) { switch (op) { case '+':cout << add_int(s1, s2) << endl; break; case '-':cout << sub_int(s1, s2) << endl; break; case '*':cout << mul_int(s1, s2) << endl; break; case '/':cout << div_int(s1, s2) << endl; break; case '%':cout << mod_int(s1, s2) << endl; break; default: cout << "The operator is error!" << endl; break; } } return 0; }
c语言实现大整数加法的实例
#include <stdio.h> #include <string.h> #define MAXLEN 1000 char a1[MAXLEN]; char a2[MAXLEN]; static int v1[MAXLEN]; static int v2[MAXLEN]; static int v3[MAXLEN]; int i, j, n, L, z; void main(void) { scanf("%d", &n); for (j = 0; j < n; j++) { scanf("%s%s", a1, a2); L = strlen(a1); for (i = 0; i < L; i++) v1[i] = a1[L - 1 - i] - '0'; //下标越小。位数越高 L = strlen(a2); for (i = 0; i < L; i++) v2[i] = a2[L - 1 - i] - '0'; for (i = 0; i < MAXLEN; i++) v3[i] = v1[i] + v2[i]; for (i = 0; i < MAXLEN; i++) { if (v3[i] >= 10) { v3[i + 1] += 1; v3[i] = v3[i] % 10; } } printf("Case %d:\n", j + 1); printf("%s + %s = ", a1, a2); z = 0; for (i = MAXLEN - 1; i >= 0; i--) { if (z == 0) { if (v3[i] != 0) { printf("%d", v3[i]); z = 1; } } else { printf("%d", v3[i]); } } if (z == 0) printf("0"); printf("\n"); } getchar(); getchar(); } //Sample Input //3 //0 0 //1 2 //112233445566778899 998877665544332211 // //Sample Output //Case 1: //0 + 0 = 0 //Case 2: //1 + 2 = 3 //Case 3: //112233445566778899 + 998877665544332211 = 1111111111111111110
代码下载
全部内容的文件夹