zoukankan      html  css  js  c++  java
  • 高精度全家福

    众所周知,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 }

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

     

  • 相关阅读:
    前端十万个为什么(之一):我们为什么需要npm?
    初识模块化开发工具:
    javascript 中的 let 作用域
    把汉字转换为html实体编码
    【小程序】开发过程问题整理
    【入门】正则表达式
    【CSS】面试知识整理
    【入门】Gulp 简单使用
    【入门】WebSocket 示例
    【JQ】$.ajax() 参数
  • 原文地址:https://www.cnblogs.com/InductiveSorting-QYF/p/10679946.html
Copyright © 2011-2022 走看看