众所周知,int型的数据范围是-2147483648~+2147483647(32位存储,有1位存符号),无符号行unsigned   int : 0~4294967295 ,long long的范围也不过-9223372036854775808~9223372036854775807  (19位数,64位存储,有1位存符号 ),无符号型unsigned long long:0~18446744073709551615(20位数)那么问题来了,如果要求计算超过20位数的数的四则运算怎么办?这里就用到高精度算法了。

高精度算法的核心思想就是用数组模拟竖式运算。首先用字符串读数,并倒着把每位数存到数组里(方便进位,想想如果正着存到数组里时最高位进位的处理可没倒着存方便啊)(注意正负号要提出,用于判断结果正负、减法顺序和对负数运算的转换)。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

核心代码:

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 }

 

总的来说高精度就是对小学竖式的模拟,只要小学学好了,打高精度岂不手到擒来?(\滑稽)

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄