我们知道任何数值都有范围一说,c++肯定也一样
int
表示32为整数
longlong
表示64位整数
数值过大就会存在溢出的情况
怎么办?
大数教你做人
大数加
string add(string a,string b)
{
string c;
int len1=a.length();
int len2=b.length();
int len=max(len1,len2);
for(int i=len1;i<len;i++)
a="0"+a;
for(int i=len2;i<len;i++)
b="0"+b;
int ok=0;
for(int i=len-1;i>=0;i--)
{
char temp=a[i]+b[i]-'0'+ok;
if(temp>'9')
{
ok=1;
temp-=10;
}
else ok=0;
c=temp+c;
}
if(ok) c="1"+c;
int pos=-1;
for(int i=0;i<c.length();i++){
if(c[i]=='0')pos=i;
else
break;
}
// cout<<pos<<endl;
if(pos==c.length()-1)return "0";
return c.substr(pos+1);
}
大数加法只是实现了简单的加减运算,记录每一位相加的结果(总的结果对10取余)以及进位(总的结果除以10)
大数减
string sub(string a,string b)
{
string c;
bool ok=0;
int len1=a.length();
int len2=b.length();
int len=max(len1,len2);
for(int i=len1;i<len;i++)
a="0"+a;
for(int i=len2;i<len;i++)
b="0"+b;
if(a<b)
{
string temp=a;
a=b;
b=temp;
ok=1;
}
for(int i=len-1;i>=0;i--)
{
if(a[i]<b[i])
{
a[i-1]-=1;
a[i]+=10;
}
char temp=a[i]-b[i]+'0';
c=temp+c;
}
int pos=0;
while(c[pos]=='0' && pos<len) pos++;
if(pos==len) return "0";
if(ok) return "-"+c.substr(pos);
return c.substr(pos);
}
大数加法和大数减法类似,如果对应位相减是负数,那么被减数的对应位数字前高一位减1,对应位加10。这是被减数减去减数就是存在的。
大数乘
string mul(string a,int b)
{
string c;
char s;
int len=a.length();
int ok=0;
for(int i=len-1;i>=0;i--)
{
int temp=(a[i]-'0')*b+ok;
ok=temp/10;
s=temp%10+'0';
c=s+c;
}
while(ok)
{
s=ok%10+'0';
c=s+c;
ok/=10;
}
return c;
}
我们假设a*b
类似于大数加法运算,a的每一位数字乘上b得到结果的当前位的初始值,当前位初始值对10取模得到结果的当前位。同时进位等于当前位初始值加上进位。
我们假设12345*12
12
* 12
每一位的初始值等于
12 24
我们从右向左对十取模并且得到进位,将进位加到高一位的位置。
那么有
第一步:4(进位为2)
第二步:12+2 4
第三步:1 4 4
结果就是144
大数除
string div(string a,int b)
{
string c;
int len=a.length();
int ans=0;
char s;
for(int i=0;i<len;i++)
{
ans=ans*10+a[i]-'0';
s=ans/b+'0';
ans%=b;
c+=s;
}
int pos=0;
while(pos<len && c[pos]=='0') pos++;
if(pos==len) return "0";
return c.substr(pos);
}
这是模拟数式运算的一种实现方法。
大家可以自己尝试一下。
总结
- 前导零
- 相加后的结果字长
- 字符串中存储的每一位的数字和我们已知的十进制表示法相反,也就是说高位在前,低位在后,而我们进行加减运算列等式的时候是低位对其进行计算,所以在计算前我们需要转换字符串的字符位置。