大数加减乘除求根源码

//设计一个支持大数运算的计算器,其中乘法使用分治法求解。该计算器支持加减乘除还有开方根运算。 #include <iostream> #include <list> #include <string> #include <cstdio> #include <cctype> #include <cmath> using namespace std; list<char> Add(list<char> s, list<char> t); list<char> Sub(list<char> s, list<char> t); list<char> Mul(list<char> s, list<char> t); void Div(list<char> s, list<char> t); void Root(list<char>); void print(list<char> ans); void printhelp() //打印帮助信息 { cout << "请选择要进行的大数运算" << endl; cout << "1:加法运算" << endl; cout << "2:减法运算" << endl; cout << "3:乘法运算" << endl; cout << "4:除法运算" << endl; cout << "5:开平方根运算" << endl; cout << "6:退出" << endl; } list<char> Add(list<char> num1,list<char> num2) //加法运算 { list<char> ans; list<char>::iterator iter1,iter2; iter1 = num1.begin(); iter2 = num2.begin(); int sign = 0; //标记结果符号 if((*iter1) == '-' && (*iter2) == '-') //如果两个数都是负数 { num1.pop_front(); num2.pop_front(); sign = 1; ans = Add(num1,num2); ans.push_front('-'); } else if((*iter1) == '-' && (*iter2) != '-') //如果一负一正 { num1.pop_front(); ans = Sub(num2,num1); } else if((*iter1) != '-' && (*iter2) == '-') //如果一正一负 { num2.pop_front(); ans = Sub(num1,num2); } else //如果都为正 { int len1,len2,i,len,carry; len1 = num1.size(); len2 = num2.size(); if(len1 >= len2) //补齐两个数的位数 { len = len1; for(i = 0; i < len1 - len2; i++) num2.push_front('0'); } else { len = len2; for(i = 0; i < len2 - len1; i++) num1.push_front('0'); } //print(num1); //print(num2); carry = 0; iter1 = num1.end(); iter2 = num2.end(); iter1--; iter2--; for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2) //进行运算 { i = (*iter1 - '0') + (*iter2 - '0') + carry; //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; ans.push_front((i % 10) + '0'); carry = i / 10; } i = (*iter1 - '0') + (*iter2 - '0') + carry; //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; ans.push_front((i % 10) + '0'); carry = i / 10; if(carry) ans.push_front(carry+'0'); } return ans; //返回结果 } list<char> Sub(list<char> num1,list<char> num2) //减法运算 { list<char> ans; int sign = 0; list<char>::iterator iter1,iter2; int len1,len2,len; iter1 = num1.begin(); iter2 = num2.begin(); if((*iter1) == '-' && (*iter2) == '-') //如果两个数都为负数 { num2.pop_front(); num1.pop_front(); ans = Sub(num2,num1); //ans.push_front('-'); } else if( (*iter1) == '-' && (*iter2) != '-') //如果一负一正 { num1.pop_front(); ans = Add(num1,num2); ans.push_front('-'); } else if( (*iter1) != '-' && (*iter2) == '-') //如果一正一负 { num2.pop_front(); ans = Add(num1,num2); } else //如果都为正 { len1 = num1.size(); len2 = num2.size(); if(len1 >= len2) //补齐位数 { len = len1; for(int i = 0; i < len1 - len2; i++) num2.push_front('0'); } else { len = len2; for(int i = 0; i < len2 - len1; i++) num1.push_front('0'); } //print(num1);cout << endl; //print(num2);cout << endl; int carry = 0,i; iter1 = num1.end(); iter2 = num2.end(); iter1--; iter2--; for(;(iter1 != num1.begin()) && (iter2 != num2.begin()); --iter1,--iter2) //进行运算 { i = (*iter1 - '0' - carry) - (*iter2 - '0'); carry = 0; if( i < 0) { i += 10; carry = 1; } //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; ans.push_front((i % 10) + '0'); } i = (*iter1 - '0' - carry) - (*iter2 - '0'); if(i < 0) { i += 10; sign = 1; } //cout << (*iter1 - '0') << " " << (*iter2 - '0') << " " << i << endl; if(i) ans.push_front(i + '0'); if(sign) ans.push_front('-'); } return ans; } list<char> Mul(list<char> num1,list<char> num2) // 分治法求两大数的积 { list<char> ans; int sign = 0; int len1,len2,len; list<char>::iterator iter1,iter2,iter; list<char> high,low; list<char> anshigh,anslow; int th,tl; int i,j,k; //print(num1);cout << endl; //print(num2);cout << endl; if(num1.size() == 1 && num2.size() == 1) //如果两数都已是一位数,则进行运算 { th = *(num1.begin()) - '0'; tl = *(num2.begin()) - '0'; th *= tl; ans.push_front( th % 10 + '0'); ans.push_front( th / 10 + '0'); return ans; } else if(num1.size() == 1 && num2.size() > 1) //如果num1位数大于1,则对Num1分治求积 { if(*(num2.begin()) == '-') { sign = 1; num2.pop_front(); } len2 = num2.size(); if(len2 == 1) { ans = Mul(num1,num2); if(sign) ans.push_front('-'); } else { for(iter= num2.begin(),i = 0; i < len2 / 2; i++,iter++) { high.push_back(*iter); } for(;iter!=num2.end();iter++) { low.push_back(*iter); } len = low.size(); anshigh = Mul(num1,high); //num1分为两部分,high,low anslow = Mul(num1,low); for(i = 0; i < len; i++) anshigh.push_back('0'); ans = Add(anshigh,anslow); //合并结果 if(sign) ans.push_front('-'); } return ans; } else if(num2.size() == 1 && num1.size() > 1) //如果num2位数大于1,则对Num2分治求积 { if(*(num1.begin()) == '-') { sign = 1; num1.pop_front(); } len1 = num1.size(); if(len2 == 1) { ans = Mul(num1,num2); if(sign) ans.push_front('-'); } else { for(iter= num1.begin(),i = 0; i < len1 / 2; i++,iter++) { high.push_back(*iter); } for(;iter!=num1.end();iter++) { low.push_back(*iter); } len = low.size(); anshigh = Mul(num2,high); //num2分为两部分,high,low anslow = Mul(num2,low); for(i = 0; i < len; i++) anshigh.push_back('0'); ans = Add(anshigh,anslow); //合并结果 if(sign) ans.push_front('-'); } return ans; } //如果两数位数都大于1,则都运用分治 else { list<char> num1high,num1low,num2high,num2low; int flag1 = 0,flag2 = 0; if(*(num1.begin()) == '-') { flag1 = 1; num1.pop_front(); } if(*(num2.begin()) == '-') { flag2 = 1; num2.pop_front(); } if((flag1 == 1 && flag2 == 0)||(flag1 == 0 && flag2 == 1)) //如果有一正一负,则标记结果为负 { sign = 1; } len1 = num1.size(); len2 = num2.size(); if(len1 == 1 || len2 == 1) //如果有一个数是一位数,则直接递归调用 { ans = Mul(num1,num2); if(sign) ans.push_front('-'); } else { //否则分治法求 for(iter = num1.begin(),i = 0; i < len1 / 2; iter++,i++) num1high.push_back(*iter); //被乘数高位部分 for( ; iter != num1.end(); iter++) num1low.push_back(*iter); //被乘数低位部分 for(iter = num2.begin(),i = 0; i < len2 / 2; iter++,i++) num2high.push_back(*iter); //乘数高位部分 for( ; iter != num2.end(); iter++) num2low.push_back(*iter); //乘数低位部分 int a = (len1 + 1) / 2; int b = (len2 + 1) / 2; list<char> AC,AD,BC,BD; //print(num2high);cout << endl; //print(num2low);cout << endl; AC = Mul(num1high,num2high); //运用X=A*10^a + B; Y= C*10^b + D; AD = Mul(num1high,num2low); // X*Y = AC * 10 ^(a+b) + AD *10^a + BC * 10 ^b + BD公式求 BC = Mul(num1low,num2high); BD = Mul(num1low,num2low); for(i = 0; i < a + b; i++) AC.push_back('0'); for(i = 0; i < a; i++) AD.push_back('0'); for(i = 0; i < b; i++) BC.push_back('0'); ans = Add(AC,AD); ans = Add(ans,BC); ans = Add(ans,BD); //累加结果 if(sign) ans.push_front('-'); } return ans; } } void Div(list<char> num1,list<char> num2) //用辗转相除求结果 { list<char> ans; list<char> temp; int len1,len2,len; int i,j,k; int sign = 0; int flag1 = 0,flag2 = 0; list<char>::iterator iter; if(*(num1.begin()) == '-') { flag1 = 1; num1.pop_front(); } if(*(num2.begin()) == '-') { flag2 = 1; num2.pop_front(); } if((flag1 == 1 && flag2 != 1) || (flag1 == 0 && flag2 == 1)) sign = 1; //标记结果符号 len1 = num1.size(); len2 = num2.size(); if(len1 < len2) //如果被除数小于除法,除数为0 { cout << "商是0;余数是" ; print(num2); cout << endl; return ; } else //用辗转相除求结果 { for(iter = num1.begin(),i = 0; i < len2 ;++i,++iter) temp.push_back(*iter); list<char> digit,res; for(j = 0; j < 10; j++) { digit.clear(); digit.push_back(j + '0'); res = Mul(num2,digit); res = Sub(temp,res); if(*(res.begin()) == '-') break; } //cout << endl;print(temp); cout << endl; j -= 1; if(j > 0) { digit.clear(); digit.push_back(j + '0'); temp = Sub(temp,num2); ans.push_back(j + '0'); } for(;iter != num1.end();++iter) { temp.push_back(*iter); for(j = 0; j < 10; j++) { digit.clear(); digit.push_back(j + '0'); res = Mul(num2,digit); res = Sub(temp,res); if(*(res.begin()) == '-') break; } //cout << endl;print(temp); cout << endl; j -= 1; digit.clear(); digit.push_back(j + '0'); res = Mul(num2,digit); temp = Sub(temp,res); ans.push_back(j + '0'); } if(sign) ans.push_front('-'); } cout << "商是"; print(ans); cout << ";余数是" ; print(temp); cout << endl; return ; } void Root(list<char> num1) //求大数的平方根,用枚举算法暴力搜索算法求 { list<char> ans; int len1; list<char> digit,temp; len1 = num1.size(); int a = len1 / 2; //a是结果的最少位数 int i; digit.push_back('1'); ans.push_back('1'); //从ans=10 ^ a 开始搜索 for(i = 0; i < a - 1; i++) ans.push_back('0'); while(true) //搜到则结束 { temp = Mul(ans,ans); temp = Sub(num1,temp); if(*(temp.begin()) == '-') //如果当前ans的平方大于num1,则得结果 break; ans = Add(ans,digit); } ans = Sub(ans,digit); print(ans); cout << endl; } list<char> translate(string input) { list<char> res; int len = input.length(); for(int i = 0; i < len; i++) res.push_back(input[i]); return res; } void print(list<char> ans) { list<char>::iterator iter; int flag = 1; iter = ans.begin(); if(*iter == '-') { cout << *iter; iter++; } for(;iter != ans.end(); ++iter) { if(*iter == '0' && flag) continue; //cout << (*iter); else { flag = 0; cout << (*iter); } } if( flag == 1) cout << 0 ;; //cout << endl; } int main() { char choice; //选择要进行的运算 list<char> num1; list<char> num2; list<char> res; string input; while(true) { cout << endl; printhelp(); cin >> choice; switch(choice) { case '1': //如果选择加法运算 cout << "请输入第一个数" << endl; cin >> input; num1 = translate(input); cout << "请输入第二个数" << endl; cin >> input; num2 = translate(input); res = Add(num1,num2); print(num1); cout << " + " ; print(num2); cout << " = "; print(res); cout << endl; break; case '2': //选择减法运算 cout << "请输入第一个数" << endl; cin >> input; num1 = translate(input); cout << "请输入第二个数" << endl; cin >> input; num2 = translate(input); res = Sub(num1,num2); print(num1); cout <<" - " ; print(num2); cout << " = "; print(res); cout << endl; break; case '3': //选择乘法运算 cout << "请输入第一个数" << endl; cin >> input; num1 = translate(input); cout << "请输入第二个数" << endl; cin >> input; num2 = translate(input); res = Mul(num1,num2); print(num1); cout <<" * " ; print(num2); cout << " = "; print(res); cout << endl; break; case '4': //选择除法运算 cout << "请输入第一个数" << endl; cin >> input; num1 = translate(input); cout << "请输入第二个数" << endl; cin >> input; num2 = translate(input); print(num1); cout << " / " ; print(num2); cout << " = "; if(num2.size() == 1 && (*(num2.begin()) == '0')) { cout << "divided zero error" << endl; break; } Div(num1,num2); //print(res); cout << endl; break; case '5': //选择求根运算 cout << "请输入第一个数" << endl; cin >> input; num1 = translate(input); if(*(num1.begin()) == '-') { cout << "负数没有实数平方根" << endl; break; } Root(num1); break; case '6': return 0; default: break; } } }

超大位数计算程序清单 1. 第一个操作数文件 A1.txt 2. 第二个操作数文件 A2.txt 3. VC6老版本程序 bc.exe 4. VC2015新版本程序 BigCom.exe 5. 新版乘法批处理 cheng.bat 6. 新版除法批处理 chu.bat 7. 新版加法批处理 jia.bat 8. 新版减法批处理 jian.bat 9. 随机测试文件生成 CreateTestFiles.py 10随机测试文件生成图形版 DataCreater.exe 说明: 1. 测试数据的构造 可以使用清单中10的软件在图形化条件下构建测试文件,但是数据是固定1位或者几位的简单重复;如果需要随机的测试数据,可以使用清单9中的python脚本。使用前可以到www.python.org下载python 2.7安装一下就可以在命令行运行,然后就能自动生成指定长度的测试文件A1和A2了。 2.测试的验证 由于数据量比较大,可以分别使用程序清单4的软件和其他5~8批处理计算结果比较,用于验证计算的结果是否一致。其中清单中5~8的批处理是调用最新版2015实现;要使用清单3老版本的程序,可以按照5~8构建对应测试批处理或者直接在命令行指定参数,例如进行乘法可以使用命令 bc m。需要注意, 测试的时候C1.txt会被覆盖,需要先重命名上一次的文件。 3.关于最大计算位数当前设定的是不超过2147483648位,即计算的结果也不能超过这个位数。 4.本次新版发布是支持Win7 x64以及以后的平台,如果需要,可以编译为Linux或者MacOS平台上进行运算。 5.文件中C1.txt是使用新版程序结算乘法的结果,C2.txt是用旧版计算的结果,可以对比一下结果一致。但使用时间相差了几十秒!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值