ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高精度运算总结

2022-05-20 16:33:41  阅读:153  来源: 互联网

标签:总结 运算 高精度 int res long -- length bigInt


日期:2022年5月18日

注:本博客中的代码仅供参考。


 

概念

数据类型 定义标识符 数据范围
整型 int -231~231-1(≈2×109
长整型 long long -263~263-1
无符号长整型 unsigned long long 0~264-1

上面给出的范围的数称为单精度数,对应的运算称为单精度运算。

超出上面给出的范围的数称为高精度数(注:尝试使用这些范围存储的话会导致溢出),对应的运算称为高精度运算。

实现方法

将输入的数字导入某一数组(注:不同的数需要导入不同数组),并在该数组中模拟计算过程,最后将数组中的数字输出。

注:数组中的每一个位置应只存储一个位数的数字,否则在输出时可能会出现问题。

代码(正片【确信】)

高精度加法

#include<bits/stdc++.h>
using namespace std;
char s[510];//这个字符数组作为数据的“中转站”,最终将数据导入数组中
struct bigInt{
    int length;//数据的长度(位数)
    int v[510];//存储数据的数组
};
bigInt operator +(bigInt a,bigInt b){//重新载入+
    int k=max(a.length,b.length);//比较尾数大小,将更大的位数作为之后相加的长度
    for(int i=1;i<=k;++i)
    {
        a.v[i]+=b.v[i];//将每一位的数相加
    }
    for(int i=1;i<=k;++i)//进位
    {
        a.v[i+1]+=a.v[i]/10;
        a.v[i]%=10;
    }
    if(a.v[k+1])
    {
        ++k;
    }//如果最高位也存在进位,增加k的长度
  //严格来说,应该检查不止一位。但因为加法最多会增加一位,所以检查与否都无足轻重,然而在高精度乘法中会显得尤为必要
    a.length=k;
    return a;
}
bigInt A,B;
int main(){
    scanf("%s",s+1);//输入数据。s+1代表数据从s[1]向后存储
    int n=strlen(s+1);//求数据的位数
    for(int i=1;i<=n;++i)
    {
        A.v[i]=s[n-i+1]-'0';//赋值。-'0'可以使数据从字符转化为数字。倒过来存储有利于后面的计算(尤其是出现最高位进位时)
    }
    A.length=n;//赋值
    scanf("%s",s+1);
    n=strlen(s+1);
    for(int i=1;i<=n;++i)
    {
        B.v[i]=s[n+1-i]-'0';
    }
    B.length=n;
    A=A+B;//相加。这里的+使用的是重新载入的+
    for(int i=A.length;i>=1;--i)
    {
        printf("%d",A.v[i]);//输出求得的和。由于数据是倒过来存储的,输出也应倒过来输出
    }
    return 0;
}

高精度减法

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=10186;
 4 struct bigInt{
 5     int length;
 6     int v[N];
 7 };
 8 bigInt A,B,C;
 9 char s[N];
10 bigInt read(){//用于读入数据的函数
11     memset(C.v,0,sizeof(C.v));
12     scanf("%s",s+1);
13     int n=strlen(s+1);
14     for(int i=1;i<=n;++i)
15     {
16         C.v[i]=s[n+1-i]-'0';
17     }
18     C.length=n;
19     return C;
20 }
21 bool operator >=(bigInt a,bigInt b){//比较两数大小
22     int m=a.length;
23     int n=b.length;
24     if(m>n)//当m与n位数不同时,位数更大的数更大
25     {
26         return true;
27     }
28     if(m<n)
29     {
30         return false;
31     }
32     for(int i=n;i>0;--i)
33     {
34         if(a.v[i]>b.v[i])//当位数相同时,从最高位向下遍历。如果某个数的某一位数字更大,则这个数更大
35         {
36             return true;
37         }
38         if(a.v[i]<b.v[i])
39         {
40             return false;
41         }
42     }
43     return true;
44 }
45 bigInt operator -(bigInt a,bigInt b){
46     int k=a.length;
47     for(int i=1;i<=k;++i)
48     {
49         if(a.v[i]<b.v[i])
50         {
51             --a.v[i+1];
52             a.v[i]+=10;
53         }
54         a.v[i]-=b.v[i];
55     }
56     while(a.v[k]==0&&k>1)
57     {
58         --k;
59     }
60     a.length=k;
61     return a;
62 }
63 int main(){
64     A=read();
65     B=read();
66     if(A>=B)
67     {
68         A=A-B;
69     }else{
70         printf("-");
71         A=B-A;
72     }//都是大的数减小的数,如果A<B时,在输出数据前面输出-
73     for(int i=A.length;i>0;--i)
74     {
75         printf("%d",A.v[i]);
76     }//同理,倒过来输出
77     return 0;
78 } 

高精度乘法

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char s[2500];
 4 int result[4005]={0},rlength;
 5 struct bigInt{
 6     int length;
 7     int v[2500];
 8 };
 9 bigInt operator *(bigInt a,bigInt b){
10     for(int i=1;i<=a.length;++i)
11     {
12         for(int j=1;j<=b.length;++j)
13         {
14             result[i+j-1]+=a.v[i]*b.v[j];
15         }
16     }
17     for(int i=1;i<=4001;++i)
18     {
19         result[i+1]+=result[i]/10;
20         result[i]%=10;
21     }
22     rlength=a.length+b.length;
23     while(result[rlength]==0&&rlength>1)
24     {
25         --rlength;
26     }//乘法最高位可能不止进一位,但因为所得结果的最多位数为A的位数,B的位数,可以从最多位数开始向后遍历,在遇到不为0的数前且位数不为1时(考虑到结果为0的情况),将估计位数缩减
27 }
28 bigInt A,B;
29 int main(){
30     scanf("%s",s+1);
31     int n=strlen(s+1);
32     for(int i=1;i<=n;++i)
33     {
34         A.v[i]=s[n+1-i]-'0';
35     }
36     A.length=n;
37     scanf("%s",s+1);
38     n=strlen(s+1);
39     for(int i=1;i<=n;++i)
40     {
41         B.v[i]=s[n+1-i]-'0';
42     }
43     B.length=n;
44     A=A*B;
45     for(int i=rlength;i>=1;--i)
46     {
47         printf("%d",result[i]);
48     }
49     return 0;
50 }

高精度除法

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=5100;
 4 struct bigInt{
 5     int length;
 6     int v[N];
 7 };
 8 bigInt operator /(bigInt a,long long b){
 9     int k=a.length;
10     long long res=0,c=0;
11     for(int i=k;i>=1;--i)//因为除法在计算时与+、-、×相反,且数据存储时依然是倒过来存储的,所以此处要从最高位开始运算
12     {
13         res=res*10+a.v[i];
14         a.v[i]=res/b;
15         res%=b;
16     /*这里的原理是:
17     ①余数(res)乘10并加上下一位
18     ②将余数整除10的结果赋给要参加运算的那一位
19     ③余数取余10
20     */
21     }
22     while(a.v[k]==0&&k>1)
23     {
24         --k;//统计位数
25     }
26     a.length=k;
27     return a;
28 }
29 bigInt A;
30 long long B;
31 char s[N];
32 int main(){
33     scanf("%s",s+1);
34     int n=strlen(s+1);
35     for(int i=1;i<=n;++i)
36     {
37         A.v[i]=s[n+1-i]-'0';
38     }
39     A.length=n;
40     scanf("%lld",&B);
41     A=A/B;
42     for(int i=A.length;i>=1;--i)
43     {
44         printf("%d",A.v[i]);
45     }
46     return 0;
47 } 

 


一些心得

  • 使用高精度运算前要思考这道题是否需要高精度(如运算结果不会溢出就不需要用高精)/是否可以简化(如题目要求或可以推出是高精和单精——写了大半天高精和高精,结果最后发现是高精和单精的心情可不好)。如题目P1591(阶乘数码)中的阶乘就可以简化为高精乘单精。
  • 在运算时也要注意开的一些数是否能完全囊括题目限定的数据范围。例如这段代码(星号处为要点):
     1 bigInt operator /(bigInt a,long long b){
     2     int k=a.length;
     3     *int res=0,c=0;
     4     for(int i=k;i>=1;--i)
     5     {
     6         res=res*10+a.v[i];
     7         a.v[i]=res/b;
     8         res%=b;
     9     }
    10     while(a.v[k]==0&&k>1)
    11     {
    12         --k;
    13     }
    14     a.length=k;
    15     return a;
    16 }

    "int res=0,c=0;"会导致余数在超过范围时出现运算错误,如计算9000000000/1000000000的结果是0。正确的处理如下:

     1 bigInt operator /(bigInt a,long long b){
     2     int k=a.length;
     3     *long long res=0,c=0;
     4     for(int i=k;i>=1;--i)
     5     {
     6         res=res*10+a.v[i];
     7         a.v[i]=res/b;
     8         res%=b;
     9     }
    10     while(a.v[k]==0&&k>1)
    11     {
    12         --k;
    13     }
    14     a.length=k;
    15     return a;
    16 }

     

 

标签:总结,运算,高精度,int,res,long,--,length,bigInt
来源: https://www.cnblogs.com/PlayerSS05/p/16286352.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有