C和C++中整数最大只能表示10位,不然就会溢出,所以出现了如何避免整数溢出的问题。其中一个方法就是使用字符串来表示,使用字符串的长度是没有限制的。
使用字符串表示整数然后进行乘法运算的关键有如下几点:
- 被乘数和乘数相乘时最开始不处理进位,而是每一位相乘的计算结果都是用整数来保存
- 第一步计算完毕之后从低位到高位开始处理进位
- 不难发现保存计算结果的整型数组的长度是被乘数的长度和乘数的长度之和
- 注意最高位的进位问题
- 将计算完毕后的整形数组转换成字符数组
- 字符数组尾端记得加上\0,整型转字符型时记得加上'0'
基本的算法步骤使用下面的图示来说明:(下面都是针对正整数的运算)
代码实现如下:
// Test9.cpp : 定义控制台应用程序的入口点。
//
#include <iostream>
#include <assert.h>
#include <sstream>
using namespace std;
void multiply(const char * str1,const char * str2)
{
assert(str1!=NULL&&str2!=NULL);
int cstr1=strlen(str1);
int cstr2=strlen(str2);
int * res=new int[cstr1+cstr2]();//注意new关键词尾端加上小括号就会将res初始化为0,特别注意小括号里不能填任何初值
//逐位处理,处理遍历字符串是从低位到高位,那么运算结果就是从整数的高位开始计算
for (int i=0;i<cstr1;i++)
{
for (int j=0;j<cstr2;j++)
{
res[i+j+1]+=int(str1[i]-'0')*int(str2[j]-'0');//首先计算的是高位,res要加上1是为了处理后面的偏移
}
}
//处理进位
for (int i=cstr1+cstr2-1;i>=1;i--)
{
if(res[i]>=10)
{
res[i-1]+=res[i]/10;
res[i]=res[i]%10;
}
}
//将int型数组保存成字符数组
char * ans=new char[cstr1+cstr2];
int k=0;
while(res[k]==0)//首先需要掉过为0的那些高位
k++;
int pos=0;
while(k<cstr1+cstr2)//执行复制操作
{
ans[pos++]=res[k++]+'0';//不要忘记了加上'0'
}
ans[pos]='\0';//最后记得字符数组尾端需要补上字符串结束标记
cout<<"计算结果为:";
for (int i=0;i<strlen(ans);i++)
{
cout<<ans[i];
}
cout<<endl;
delete [] res;
delete [] ans;
}
int main()
{
string s;
stringstream ss;
cout<<"输入两个数,以空格隔开:"<<endl;
while(getline(cin,s))
{
ss.clear();
ss<<s;
string s1,s2;
ss>>s1>>s2;
multiply(s1.c_str(),s2.c_str());
}
getchar();
return 0;
}
测试输出:
同样的思路可以处理大整数的加法:
关键的函数如下:
void add(const char * str1,const char * str2)
{
assert(str1!=NULL&&str2!=NULL);
int cstr1=strlen(str1);
int cstr2=strlen(str2);
int maxLen=max(cstr1,cstr2)+1;
int * res=new int[maxLen]();
int minLen=min(cstr1,cstr2);
int k=0;
int i=cstr1-1,j=cstr2-1 ;
//从字符串尾端开始遍历起,将结果保存在res数组中
for (;i>=0&&j>=0;i--,j--)
{
res[k]=str1[i]-'0'+str2[j]-'0';
k++;
}
//对于较长的字符串,直接将它添加到res尾端即可
while (i>=0)
res[k++]=str1[i--]-'0';
while(j>=0)
res[k++]=str2[j--]-'0';
//处理进位
for (int m=0;m<maxLen-1;m++)
{
res[m+1]+=res[m]/10;
res[m]=res[m]%10;
}
//将结果集的高位去除
k=maxLen-1;
while(res[k]==0)
k--;
char * ans=new char[maxLen];
int m=k,n=0;
//需要从res数组中从高位开始取数
for (;m>=0;m--,n++)
{
ans[n]=res[m]+'0';
}
ans[n]='\0';
cout<<"计算结果为:"<<ans<<endl;
}
测试输出: