高精度算法
高精度加法
问:为什么会高精度加法?
答:因为数学类型的表示范围有限,以 int 为占用 4 字节,32 位,数据范围为( -232~232-1)。大概能表示 109的数据,要是超过此范围,将无法表示。
原理
就是将数一位一位的拆分,进行相加,逢十进一。
例题
步骤
- 创建两个字符串;
- 创建三个整形数组;
- 分别将两个字符串倒序存入连个整形数组中;
- 将两个整形数组相加到第三个整形数组;
- 循环遍历第三个整形数组将大于9的元素进行除法和取;
- 倒序输出。
1 & 2
string s1,s2;
int x[N],y[N],z[N]={0};
3 & 4 & 5
// 将字符串中元素逆序存进数组中
for(int i=0;i<s1.size();i++)
x[s1.size()-i-1]=s1[i]-'0';
for(int i=0;i<s2.size();i++)
y[s2.size()-i-1]=s2[i]-'0';
// 判断两个字符串长度,把长度最长的给 len
int len=s1.size()>s2.size()?s1.size():s2.size();
// 数组相加
for(int i=0;i<len;i++)
z[i]=x[i]+y[i];
// 循环遍历大于9(或者大于等于10)的元素,进行除法和取模
for(int i=0;i<len;i++)
{
if(z[i]>9)
{
z[i+1]+=z[i]/10;
z[i]%=10;
}
}
6
// 判断z[len]是否为0,增加位数
if(z[len]!=0)
len++;
for(int i=len-1;i>=0;i--)
cout<<z[i];
完整代码
#include<iostream>
using namespace std;
const int N=1e5+10;
string s1,s2;
int x[N]={0},y[N]={0},z[N]={0};
int main()
{
getline(cin,s1);
getline(cin,s2);
for(int i=0;i<s1.size();i++)
x[s1.size()-i-1]=s1[i]-'0';
for(int i=0;i<s2.size();i++)
y[s2.size()-i-1]=s2[i]-'0';
int len=s1.size()>s1.size()?s1.size():s2.size();
for(int i=0;i<len;i++)
z[i]=x[i]+y[i];
for(int i=0;i<len;i++)
{
if(z[i]>9)
{
z[i+1]+=z[i]/10;
z[i]%=10;
}
}
if(z[len]!=0)
len++;
for(int i=len-1;i>=0;i--)
cout<<z[i];
return 0;
}
高精度减法
高精度减法和高精度加法基本类似。
例题
步骤
定义变量
const int N=1e5+10; //可根据实际情况进行增加或减少
int a[N]={0},b[N]={0},c[N]={0};
string s1,s2;
char flag='+'; //用于判断正负数
判断字符串长度和字典序
//如果s1的长度小于或等于s2,且s1的字典序小于s2,就需要进行交换,并改变flag
if(s1.size()<s2.size()||s1.size()==s2.size()&&s1<s2)
{
flag='-';
swap(s1,s2)
}
相减
// 如果a[i]小于b[i],就需要向前借一位。
for(int i=0;i<s1.size()-1;i++)
{
if(a[i]<b[i])
{
a[i]+=10;
a[i+1]--;
}
c[i]=a[i]-b[i];
}
输出
// 需要判断从第几位开始逆序输出
int index=0;
for(int i=s1.size()-1;i>=0;i--)
{
if(c[i]!='0')
{
index=i;
break;
}
}
// 判断正负数
if(flag=='-')
cout<<'-';
完整代码
#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N]={0},b[N]={0},c[N]={0};
string s1,s2;
int main()
{
char flag='+';
getline(cin,s1);
getline(cin,s2);
if(s1.size()<s2.size()||s1.size()==s2.size()&&s1<s2)
{
swap(s1,s2);
flag='-';
}
for(int i=0;i<s1.size();i++) a[s1.size()-1-i]=s1[i]-'0';
for(int i=0;i<s2.size();i++) b[s2.size()-1-i]=s2[i]-'0';
for(int i=0;i<s1.size();i++)
{
if(a[i]<b[i])
{
a[i]+=10;
a[i+1]--;
}
c[i]=a[i]-b[i];
}
int index=0;
for(int i=s1.size()-1;i>=0;i--)
{
if(c[i]!=0)
{
index=i;
break;
}
}
if(flag=='-')
cout<<'-';
for(int i=index;i>=0;i--)
cout<<c[i];
return 0;
}
高精度乘法
!!!这里的 t 是进位的意思,另外还需要判断一下如果n为0直接结束程序输出入0
例题
步骤
定义变量
const int N=1e5+10; //可根据题目条件自行增加
int a[N],b[N],n;
string s1;
int t=0,len=0; //t是进位,len用于记录长度
n 为 0
if(!n)
cout<<0;
n 不为 0
//将字符串内容倒序存入数组a中
for(int i=0;i<s1.size();i++)
a[s1.size()-i-1]=s1[i]-'0';
//s1的每一位与n相乘
for(int i=0;i<s1.size()||t;i++)
{
if(i<s1.size()) t+=a[i]*n;
b[i]=t%10;
len++; //用于记录位数
t/=10;
}
完整代码
#include<iostream>
using namespace std;
string s1;
int n;
const int N=1e5+10;
int a[N],b[N];
int main()
{
int t=0,len=0;
getline(cin,s1);
cin>>n;
if(!n) cout<<0;
else
{
for(int i=0;i<s1.size();i++)
a[s1.size()-i-1]=s1[i]-'0';
for(int i=0;i<s1.size()||t;i++)
{
if(i<s1.size()) t+=a[i]*n;
b[i]=t%10;
len++;
t/=10;
}
for(int i=len-1;i>=0;i--)
cout<<b[i];
}
return 0;
}
高精度除法
这里 r 是指余数,n 为除数,高精度除法与前面—高精度(加/减/乘法)不同在于不用讲字符串倒序存入整型数组中。
例题
794. 高精度除法
步骤
定义变量
const int N=1e5+10; //可根据题自行增加减少
int a[N],b[N],n; //n为除数
string s;
int len=0,cnt=0,r=0; //r是余数,cnt记录0的个数,len记录位数
实现
for(int i=0;i<s.size();i++)
{
r=r*10+a[i];
b[i]=r/n;
r%=n;
len++;
if(!b[i]) cnt++;
}
输出
if(cnt==len) cout<<0; //如果(cnt记录0的个数)cnt的位数与 len 相等则直接输入一个0即可
else
{
//用于判断从第几位输出
int index=0;
for(int i=0;i<len;i++)
{
if(b[i]!=0)
{
index=i;
break;
}
}
for(int i=index;i<len;i++) cout<<b[i];
}
//最后输出余数即可
0cout<<endl<<r<<endl;
完整代码
#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N],n,b[N];
string s;
int main()
{
getline(cin,s);
cin>>n;
for(int i=0;i<s.size();i++) a[i]=s[i]-'0';
int r=0,cnt=0,len=0;
for(int i=0;i<s.size();i++)
{
r=r*10+a[i];
b[i]=r/n;
r%=n;
len++;
if(!b[i]) cnt++;
}
if(cnt==len) cout<<0;
else
{
int index=0;
for(int i=0;i<len;i++) if(b[i]!=0) {index=i;break;}
for(int i=index;i<len;i++) cout<<b[i];
}
cout<<endl<<r<<endl;
return 0;
}