高精度问题之大数相加(原来就是用字符串相加,模拟手算这么简单!)
解题心的: 就是基本的一对一模拟手算。。借助c++的string 不用逆序运算了。很方便的补0. 最后处理下前导0的问题。
#include <iostream> #include <string> using namespace std; // 实现大数相加 结果存放在num中 void bigIntergerAdd(string &num, string add) { int goBit = 0; // 存放进位 // 先交换下顺序 加数的位数要比较少 if (num.length() < add.length()) { string tmp = num; num = add; add = tmp; } string tmp (num.length() - add.length(), '0'); add = tmp + add; // 利用string的+号特性 不采用逆序相加法 int len1 = num.length(), len2 = add.length(); for (int i = len1 -1 ; i>= 0; --i) { int tmp = ((num[i] - '0') + (add[i] - '0') + goBit) ; num[i] = tmp% 10 + '0'; goBit = tmp/10; } // 特殊情况处理 if (goBit != 0) num.insert(0, string(1, (char)goBit +'0')); } int main(int argc, char** argv) { string s1; string result; int i =0; while (cin>> s1) { if (s1 == "0") { cout<< result<< endl; break; } if (i ==0) { i=1; result = s1; } else bigIntergerAdd(result, s1); } return 0; }
参考:http://blog.csdn.net/wu5151/article/details/47100085
----------------------------------------------------------------------------------
大数相乘:总的思路比较简单, 就是模拟手算。 用较短(或相等)长度的数的每一位与较长数一一相乘。要注意的是,相乘所得结果需要补0的细节 。然后就是单纯的大数相加。
#include <iostream> #include <string> using namespace std; // 大数相乘 string bigIntegerPlus(string res, string plusN) { string ret; if (res.length()< plusN.length()) { string tmp = res; res = plusN; plusN = tmp; } int len1 = res.length(), len2 = plusN.length(); for (int i = len2-1; i>=0; --i ) { string tmp(len1, '0'); // 存放相乘的中间结果 int goBit =0; for (int j= len1-1; j >=0; --j) { int mid = (res[j] -'0') * (plusN[i] -'0') + goBit; tmp[j] = mid%10 + '0'; goBit = mid /10; } if (goBit != 0) tmp.insert(0, string(1,goBit +'0')); for (int m=0; m< len2 -1-i; ++m) tmp.push_back('0'); // 补位 // 相乘后就相加 大数相加 if (i == len2-1) ret = tmp; else { int goBit2 =0; string s(tmp.length() - ret.length() ,'0'); ret = s + ret; for (int m = tmp.length()-1; m>=0; --m) { int mid = (tmp[m] -'0')+(ret[m] - '0') + goBit2; ret[m] = mid %10 +'0'; goBit2 = mid/ 10; } if (goBit2 != 0) ret.insert(0, string(1,goBit +'0')); } } // 去掉前导0 while (ret.length() >1 && ret[0] == '0') ret.erase(0,1); return ret; } int main(int argc, char** argv) { string res, plusN; while (cin>> res>> plusN) { cout<< bigIntegerPlus(res, plusN)<< endl; } return 0; }
参考:http://blog.csdn.net/wu5151/article/details/47099971
----------------------------------------------------------------------------------
实现的是大数跟int类型的相除和求余,解题心得: 模拟手算的过程。需要注意的是。其中余数的存放要用long long存放比较好。因为如果采用int类型那么 rem = prem * 10/*向后退一位*/ + src[i] - '0'; 这行代码可能会出现溢出问题。
#include <iostream> #include <cstring> using namespace std; void bigDivision(char *src, int num, char sign) { long long rem = 0; // 存放新余数 long long prem = 0; // 原余数 char res[10000] =""; bool flag = true; int k = 0; for (int i=0; i< strlen(src); ++i) { rem = prem * 10/*向后退一位*/ + src[i] - '0'; if (rem / num >0 || rem ==0) { res[k++] = rem/ num + '0'; prem = rem %num; flag = false; } else { prem = rem; if (!flag) res[k++] = '0'; } } if (sign == '%') { cout<< prem<< endl; return; } for (int i =0; i< k; ++i) cout<< res[i]; cout<< endl; } int main(int argc, char** argv) { char src[10000] = ""; int num; char sign; while (scanf("%s %c %d", src, &sign, &num) != EOF) { bigDivision(src, num, sign); } return 0; }
参考:http://blog.csdn.net/wu5151/article/details/47100165
----------------------------------------------------------------------------------
高精度问题之大数求幂,解题思路: 因为做了大数相加 ,这题也就没什么好思考的。不同之处就是先去掉小数点,计算结果后在适当位置插入小数点即可。这个算法可以计算更大的数。但必须包含小数点。。。。。。
#include <iostream> #include <string> using namespace std; // 求幂 思路: 先变成整数相乘 然后根据小数的位数 结合幂 算出小数点该结果字符串的位置 即可 string bigIntegerPlus(string src, string num) { string tmp = src; for (int i =num.length() -1; i >= 0 ; --i) { string mid(tmp.length(),'0'); int goBit =0; for (int j = tmp.length()-1; j >= 0; --j) { int tm = goBit + (tmp[j] -'0')* (num[i] - '0'); mid[j] = tm% 10 +'0'; goBit = tm /10; } for (int q = num.length()-1; q> i; --q) mid.push_back('0'); if (goBit != 0) mid.insert(0, string(1, (char)goBit +'0')); // 加法运算 if (i == num.length()-1) src = mid; else { goBit =0; string s(mid.length() - src.length(), '0'); src = s + src; for (int j = mid.length()-1; j>=0; --j) { int tm = (mid[j] - '0') +(src[j] - '0') + goBit; src[j] = tm %10 + '0'; goBit = tm /10; } if (goBit !=0) src.insert(0, string(1, (char)goBit +'0')); } } return src; } int main(int argc, char** argv) { string str; while ( getline(cin, str)) { // 分割出待积数 和 幂 以及小数点位置 int i =0; int index = 0;// 小数位置 int count = 0;//幂次数 string num; while ( i< str.length()) { if ( str[i] != ' ') { if (str[i] == '.') index = i; else num.push_back(str[i]); ++i; continue; } while ( !isdigit(str[i])) ++i; if (i + 1 == str.length()) count = str[i] - '0'; else count = (str[i] - '0') * 10 + str[i+1] - '0'; break; } index = num.length() - index; string res = num; for (int i =0; i< count-1; ++i) { res = bigIntegerPlus( res, num); } index = index * count; res.insert(res.length() - index, string(".")); while (res.length() >1 && res[0] == '0') res.erase(0, 1); for (int i =res.length()-1; i>=0; --i) { if (res[i] == '0' ) res.erase(i, i+1); else break; } cout<< res<< endl; } return 0; }