众所周知,int型的数据范围是-2147483648~+2147483647(32位存储,有1位存符号),无符号行unsigned int : 0~4294967295 ,long long的范围也不过-9223372036854775808~9223372036854775807 (19位数,64位存储,有1位存符号 ),无符号型unsigned long long:0~18446744073709551615(20位数)那么问题来了,如果要求计算超过20位数的数的四则运算怎么办?这里就用到高精度算法了。
高精度算法的核心思想就是用数组模拟竖式运算。首先用字符串读数,并倒着把每位数存到数组里(方便进位,想想如果正着存到数组里时最高位进位的处理可没倒着存方便啊)(注意正负号要提出,用于判断结果正负、减法顺序和对负数运算的转换)。
核心代码:
1 scanf("%s", str);
2 int len=strlen(str);
3 for(int i=len-1;i>=0;i--)a[len-i]=str[i]-'0'; //不要忘了把“字符数”转化为“数字数”
(为方便讨论,下面情况均为正数之间的运算。若有负数,提出负号来,并转换成相应的正数运算并把结果相应取负)
1.高精度加法:最简单的高精度运算,只需注意进位就可。从最低位开始相加,每位上的数若超过十就进下一位同时把当前位模10;
核心代码:
1 for( i=1;i<=strlen(s1)||i<=strlen(s2);i++){
2 c[i]=a[i]+b[i];
3 if(c[i]>=10){ c[i+1]++; c[i]%=10;}
4 }
5 if(c[i+1]>0) i++;
6 while(c[i]==0&&i>0) i--;
2.高精度减法:也很简单的高精度运算。先判断两数大小,让大的减小的,若一开始的被减数小于减数,则在结果前补上负号。从最低位减起,注意借位即可。
核心代码:
for(i=1;i<=strlen(s1);i++)
{
c[i]=a[i]-b[i];
if(c[i]<0){
c[i]+=10;
c[i+1]--;
}
}
while(c[i]==0&&i>0)i--;
3.高精度乘法:只是一开始的规律相对于前两个高精度运算来说较难理解罢了。回忆小学乘法竖式的学习(滑稽),我们算第一个数第i位乘第二个数第j位的结果写到竖式分割线下面第i+j-1的位置上并进位。
核心代码:
1 n=strlen(s1),m=strlen(s2);
2 for(int i=1;i<=n;i++)
3 for(int j=1;j<=m;j++)
4 c[i+j-1] += a[i]*b[j];
5
6 for(int i=1;i<=n+m-1;i++){
7 c[i+1]+=c[i]/10;
8 c[i]%=10;
9 }
10 n=n+m-1;
11 while(c[n+1]>0)n+=1;
4高精度除法:高精度劝退知识点,众多老师口中的“不要求”……好吧,言归正传,分为大数除以小数和大数除以大数的情况:
(1)大数除以小数(小数在数据类型范围内):
从被除数最高位开始试除除数,商写到竖式横线上面的对应位,留下的余数乘10再加上下位并继续试除直到最后一位。、
核心代码:
1 n=strlen(s1);
2 for(int i=n;i>0;i--){
3 c[i]=a[i]/B;
4 a[i-1]+=(a[i]%B)*10;
5 }
6 while(c[n]==0 && n>0)n--;
(2)大数除以大数(两个大数组相爱相杀的那些事儿~)
从被除数的第(被除数的位数-除数的位数)位开始,将被除数数前面的数组及当前位单独与除数相减至差小于除数,减法的次数即在写在此位的商(减法模拟除法),在把剩下的
数与下一位继续减除数算下一位。。。直到把最后一位算完。
核心代码(好像80%都是核心):
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 using namespace std;
5 int a[301],b[301],c[301];
6 void init(int a[])
7 {
8 char s[302];
9 cin>>s;
10 a[0]=strlen(s);//位数
11 for(int i=1;i<=a[0];++i)
12 a[i]=s[a[0]-i]-'0';
13 }
14 void fuyin(int p[],int q[],int det)
15 {
16 for(int i=1;i<=p[0];++i) q[det+i-1]=p[i];
17 q[0]=det+p[0]-1;
18 }
19 int compare(int a[],int b[])
20 {
21 if(a[0]>b[0]) return 1;
22 if(a[0]<b[0]) return -1;
23 for(int i=a[0];i>=1;--i)
24 {
25 if(a[i]>b[i]) return 1;
26 if(a[i]<b[i]) return -1;
27 }
28 return 0;
29 }
30 void jian(int a[],int b[])
31 {
32 if(compare(a,b)==0){a[0]=0;return;}
33 for(int i=1;i<=a[0];++i)
34 {
35 if(a[i]<b[i])
36 {
37 a[i+1]--;
38 a[i]+=10;
39 }
40 a[i]-=b[i];
41 }
42 while(a[a[0]]==0&&a[0]>0) a[0]--;
43 }
44 void chuhao(int a[],int b[],int c[])
45 {
46 int tep[302];
47 c[0]=a[0]-b[0]+1;
48 for(int i=c[0];i>=1;--i)
49 {
50 memset(tep,0,sizeof(tep));
51 fuyin(b,tep,i); //把除数拷贝到与被除数当前位一样“高”的地方
52 while(compare(a,tep)>=0) {c[i]++;jian(a,tep);} //当前位及以上单独减除数并记录减法次数(商)直到减不起 。
53 }
54 while(c[c[0]]==0&&c[0]>0) c[0]--;
55 }
56 void print(int a[])
57 {
58 if(a[0]==0) cout<<0;
59 else
60 {
61 for(int i=a[0];i>=1;--i)
62 cout<<a[i];
63 }
64 cout<<endl;
65 }
66 int main()
67 {
68 init(a);//被除数
69 init(b);//除数
70 chuhao(a,b,c);
71 print(c);//输出商
72 print(a);//输出被除数被除数各种减完剩下的——余数
73 return 0;
74 }
总的来说高精度就是对小学竖式的模拟,只要小学学好了,打高精度岂不手到擒来?(滑稽)