C++ 大数版的加减乘除代码实现总结
2015-10-05 10:39
555 查看
1)大正整数的加法
具体思路就是模仿手算的加法,我在这里先将输入的字符串reverse便于操作,最后去掉结果的前置0即可。注意:如果答案就是0,那么需要特殊处理。
大量的测试数据可以 上交至hdu 1002
[cpp] view
plaincopy
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int m=0;
int l=0;
for(int i=1;i<=n;i++)
{
string s1,s2,s(10000,'0');
cin>>s1>>s2;
m++;
cout<<(l++?"\n":"");
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
for(int j=0;j<s1.length();j++)
s[j]=s1[j];
int temp=0;
for(int k=0;k<s2.length();k++)
{
temp+=s[k]-48+s2[k]-48;
s[k]=temp%10+'0';
temp/=10;
}
s[s2.length()]=s[s2.length()]-48+temp+48;
reverse(s.begin(),s.end());
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
cout<<"Case "<<m<<":"<<endl;
cout<<s1<<" + "<<s2<<" = "<<s.substr(s.find_first_not_of('0'))<<endl;
}
return 0;
}
(2)大正整数的减法
同样是模拟手算,处理借位。用大的减去小的,最后再判断是否需要添加负号。
[cpp] view
plaincopy
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int strComp(string &s1,string &s2)
{
int len1=s1.length();
int len2=s2.length();
if(len1>len2)
return 0;
else if(len1<len2)
return 1;
else{
if(s1>=s2)
return 0;
else
return 1;
}
}
int main()
{
string s1,s2;
while(cin>>s1>>s2)
{
string s(10000,'0');
bool fgEx=true;
if(strComp(s1,s2)==1)
{
string temp;
temp=s1;
s1=s2;
s2=temp;
fgEx=false;
}
if(s1==s2)
{
cout<<s1<<" - "<<s2<<" = "<<"0"<<endl;
continue;
}
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
for(int i=0;i<s1.length();i++)
s[i]=s1[i];
for(int i=0;i<s2.length();i++)
{
if(s[i]>=s2[i])
s[i]=s[i]-'0'-(s2[i]-'0')+'0';
else{
s[i+1]=s[i+1]-'0'-1+'0';
s[i]=s[i]-'0'+10-(s2[i]-'0')+'0';
}
}
if(fgEx==false)
{
reverse(s2.begin(),s2.end());
cout<<s2<<" - ";
reverse(s1.begin(),s1.end());
cout<<s1<<" = ";
reverse(s.begin(),s.end());
cout<<"-"<<s.substr(s.find_first_not_of('0'))<<endl;
}
else
{
reverse(s1.begin(),s1.end());
cout<<s1<<" - ";
reverse(s2.begin(),s2.end());
cout<<s2<<" = ";
reverse(s.begin(),s.end());
cout<<s.substr(s.find_first_not_of('0'))<<endl;
}
}
return 0;
}
(3)大正整数乘法
还是模拟手算,第一个字符串的第i位乘以第二个字符串的第j位一定是结果的第i+j位,如果i+j已经有值,直接加上去就OK,别忘了处理进位。
这样的算法的复杂度是O(n2).利用FFT可以将算法优化到O(nlogn),关于FFT的实现在此不再赘述,可以参考算法导论或者 http://www.cnblogs.com/lsx54321/archive/2012/07/20/2601632.html。同样可提交至poj 2389。
[cpp] view
plaincopy
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string s1,s2;
while(cin>>s1>>s2)
{
string s(1000,'0');
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
for(int i=0;i<s1.length();i++)
for(int j=0;j<s2.length();j++)
{
int temp=(s1[i]-'0')*(s2[j]-'0');
s[i+j+1]=s[i+j+1]-'0'+(s[i+j]-'0'+temp)/10+'0';
s[i+j]=(s[i+j]-'0'+temp)%10+'0';
}
reverse(s.begin(),s.end());
if(s.find_first_not_of('0')==string::npos)
cout<<"0"<<endl;
else
cout<<s.substr(s.find_first_not_of('0'))<<endl;
}
return 0;
}
(4)大整数除法
我们将除法看作是减法来处理,用被减数不断的减去减数,记录减的次数即是商的值。但是我们当然不能一个一个减,因为如果有10000000/1这种情况不是要减到猴年马月。
我们可以记录被减数和减数的位数之差len,将减数扩大10的len倍。然后依次去减,一旦被减数小于减数时,将减数减小10倍,直至到原值。依次循环,去掉前置0,得出结果。
[cpp] view
plaincopy
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int strComp(string &s1,string &s2)
{
int len1=s1.length();
int len2=s2.length();
if(len1>len2)
return 0;
else if(len1<len2)
return 1;
else{
if(s1>=s2)
return 0;
else
return 1;
}
}
string Sub(string s1,string s2)
{
if(strComp(s1,s2)==1)
return "-1";
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
string s(1000,'0');
for(int i=0;i<s1.length();i++)
s[i]=s1[i];
for(int i=0;i<s2.length();i++)
{
if(s[i]>=s2[i])
s[i]=s[i]-'0'-(s2[i]-'0')+'0';
else{
s[i+1]=s[i+1]-'0'-1+'0';
s[i]=s[i]-'0'+10-(s2[i]-'0')+'0';
}
}
reverse(s.begin(),s.end());
if(s.find_first_not_of('0')==string::npos)
return "0";
else
return s.substr(s.find_first_not_of('0'));
}
int main()
{
string s1,s2;
while(cin>>s1>>s2)
{
string s(1000,'0');
if(strComp(s1,s2)==1)
{
cout<<"0"<<endl;
continue;
}
int len1=s1.length();
int len2=s2.length();
int dis=len1-len2;
for(int i=0;i<dis;i++)
s2+='0';
string ans(1000,'0');
while(dis>=0)
{
int sum=0;
string temp;
while((temp=Sub(s1,s2))!="-1")
{
sum++;
s1=temp;
}
ans[ans.length()-dis-1]=sum+'0';
dis--;
s2=s2.substr(0,len2+dis);
}
if(ans.find_first_not_of('0')==string::npos)
cout<<"0"<<endl;
else{
string res=ans.substr(ans.find_first_not_of('0'));
cout<<res<<endl;
}
}
return 0;
}
具体思路就是模仿手算的加法,我在这里先将输入的字符串reverse便于操作,最后去掉结果的前置0即可。注意:如果答案就是0,那么需要特殊处理。
大量的测试数据可以 上交至hdu 1002
[cpp] view
plaincopy
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int m=0;
int l=0;
for(int i=1;i<=n;i++)
{
string s1,s2,s(10000,'0');
cin>>s1>>s2;
m++;
cout<<(l++?"\n":"");
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
for(int j=0;j<s1.length();j++)
s[j]=s1[j];
int temp=0;
for(int k=0;k<s2.length();k++)
{
temp+=s[k]-48+s2[k]-48;
s[k]=temp%10+'0';
temp/=10;
}
s[s2.length()]=s[s2.length()]-48+temp+48;
reverse(s.begin(),s.end());
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
cout<<"Case "<<m<<":"<<endl;
cout<<s1<<" + "<<s2<<" = "<<s.substr(s.find_first_not_of('0'))<<endl;
}
return 0;
}
(2)大正整数的减法
同样是模拟手算,处理借位。用大的减去小的,最后再判断是否需要添加负号。
[cpp] view
plaincopy
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int strComp(string &s1,string &s2)
{
int len1=s1.length();
int len2=s2.length();
if(len1>len2)
return 0;
else if(len1<len2)
return 1;
else{
if(s1>=s2)
return 0;
else
return 1;
}
}
int main()
{
string s1,s2;
while(cin>>s1>>s2)
{
string s(10000,'0');
bool fgEx=true;
if(strComp(s1,s2)==1)
{
string temp;
temp=s1;
s1=s2;
s2=temp;
fgEx=false;
}
if(s1==s2)
{
cout<<s1<<" - "<<s2<<" = "<<"0"<<endl;
continue;
}
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
for(int i=0;i<s1.length();i++)
s[i]=s1[i];
for(int i=0;i<s2.length();i++)
{
if(s[i]>=s2[i])
s[i]=s[i]-'0'-(s2[i]-'0')+'0';
else{
s[i+1]=s[i+1]-'0'-1+'0';
s[i]=s[i]-'0'+10-(s2[i]-'0')+'0';
}
}
if(fgEx==false)
{
reverse(s2.begin(),s2.end());
cout<<s2<<" - ";
reverse(s1.begin(),s1.end());
cout<<s1<<" = ";
reverse(s.begin(),s.end());
cout<<"-"<<s.substr(s.find_first_not_of('0'))<<endl;
}
else
{
reverse(s1.begin(),s1.end());
cout<<s1<<" - ";
reverse(s2.begin(),s2.end());
cout<<s2<<" = ";
reverse(s.begin(),s.end());
cout<<s.substr(s.find_first_not_of('0'))<<endl;
}
}
return 0;
}
(3)大正整数乘法
还是模拟手算,第一个字符串的第i位乘以第二个字符串的第j位一定是结果的第i+j位,如果i+j已经有值,直接加上去就OK,别忘了处理进位。
这样的算法的复杂度是O(n2).利用FFT可以将算法优化到O(nlogn),关于FFT的实现在此不再赘述,可以参考算法导论或者 http://www.cnblogs.com/lsx54321/archive/2012/07/20/2601632.html。同样可提交至poj 2389。
[cpp] view
plaincopy
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string s1,s2;
while(cin>>s1>>s2)
{
string s(1000,'0');
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
for(int i=0;i<s1.length();i++)
for(int j=0;j<s2.length();j++)
{
int temp=(s1[i]-'0')*(s2[j]-'0');
s[i+j+1]=s[i+j+1]-'0'+(s[i+j]-'0'+temp)/10+'0';
s[i+j]=(s[i+j]-'0'+temp)%10+'0';
}
reverse(s.begin(),s.end());
if(s.find_first_not_of('0')==string::npos)
cout<<"0"<<endl;
else
cout<<s.substr(s.find_first_not_of('0'))<<endl;
}
return 0;
}
(4)大整数除法
我们将除法看作是减法来处理,用被减数不断的减去减数,记录减的次数即是商的值。但是我们当然不能一个一个减,因为如果有10000000/1这种情况不是要减到猴年马月。
我们可以记录被减数和减数的位数之差len,将减数扩大10的len倍。然后依次去减,一旦被减数小于减数时,将减数减小10倍,直至到原值。依次循环,去掉前置0,得出结果。
[cpp] view
plaincopy
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int strComp(string &s1,string &s2)
{
int len1=s1.length();
int len2=s2.length();
if(len1>len2)
return 0;
else if(len1<len2)
return 1;
else{
if(s1>=s2)
return 0;
else
return 1;
}
}
string Sub(string s1,string s2)
{
if(strComp(s1,s2)==1)
return "-1";
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
string s(1000,'0');
for(int i=0;i<s1.length();i++)
s[i]=s1[i];
for(int i=0;i<s2.length();i++)
{
if(s[i]>=s2[i])
s[i]=s[i]-'0'-(s2[i]-'0')+'0';
else{
s[i+1]=s[i+1]-'0'-1+'0';
s[i]=s[i]-'0'+10-(s2[i]-'0')+'0';
}
}
reverse(s.begin(),s.end());
if(s.find_first_not_of('0')==string::npos)
return "0";
else
return s.substr(s.find_first_not_of('0'));
}
int main()
{
string s1,s2;
while(cin>>s1>>s2)
{
string s(1000,'0');
if(strComp(s1,s2)==1)
{
cout<<"0"<<endl;
continue;
}
int len1=s1.length();
int len2=s2.length();
int dis=len1-len2;
for(int i=0;i<dis;i++)
s2+='0';
string ans(1000,'0');
while(dis>=0)
{
int sum=0;
string temp;
while((temp=Sub(s1,s2))!="-1")
{
sum++;
s1=temp;
}
ans[ans.length()-dis-1]=sum+'0';
dis--;
s2=s2.substr(0,len2+dis);
}
if(ans.find_first_not_of('0')==string::npos)
cout<<"0"<<endl;
else{
string res=ans.substr(ans.find_first_not_of('0'));
cout<<res<<endl;
}
}
return 0;
}
相关文章推荐
- C/C++ 注释规范
- 程序设计基石与实践系列之能让你成为Top程序员的十个C语言资源
- VC++ 中简单操作MP3音乐的方法,小结
- C语言:查找算法
- C++中的也能使用正则表达式
- C++可变参数模板的小知识
- C/C++ 拾遗
- c++组合模式和原型模式一起使用
- 带你玩转Visual Studio——带你发布自己的工程库
- 10.4做题--USACO1.2方格转换
- C/C++中typedef关键字总结
- 【小游戏】俄罗斯方块(C++版)
- 【小游戏】俄罗斯方块(C++版)
- C语言的链接属性的个人理解
- C++primer学习:string类的练习(2)
- C++primer学习:string的操作习题(1):
- CPPUTest 单元测试框架(针对 C 单元测试的使用说明)
- C++学习笔记6——类的多态
- 【小游戏】C++打造2048控制台版本
- 【小游戏】C++打造2048控制台版本