高精度算法(加法,减法,乘法,除法 详细篇)

高精度算法(加法,减法,乘法,除法)
(弱驹一枚,有错误欢迎来指点,谢谢)

哈喽!
在我们日常 敲 (qian) 代 (tu) 码 (guang) 时 (ming), 是不是会经常遇见高精度的 加法, 减法, 乘法, 除法 呢?,相信你遇到过需要用到高精度的题目。在我们还没接触高精度算法的时候,当需要把两个贼大的数相加的时候,我们会想到把两个变量定义成(long long型 ,double型) 这两种应该是我们还没接触高精度算法时所能想到的(定义较大变量),其中double(双精度浮点数)使用 64 位(8字节) 来储存一个浮点数。 它 仅仅 可以表示十进制的15或16位有效数字,负值取值范围为 -1.7976E+308 到 -4.94065645841246544E-324,正值取值范围为 4.94065645841246544E-324 到 1.797693E+308
所以当我们要进行两个大数相加时,上面两种是远远不够的,所以我们需要学高精度算法

例1、高精度加法
先上例题
题目描述
高精度加法,x相当于a+b problem,不用考虑负数

输入输出格式
输入格式:
分两行输入a,b<=10^500

输出格式:
输出只有一行,代表A+B的值

( 10^500 非常大,所以要用高精度算法来解决这道题 )

方法要领
肝就完了

 正着读入,倒着输出,用字符串数组进行模拟加法

1、定义字符数组或字符串
(char str[666],str1[666],str2[666]; ) | | ( string str ,str1, str2;) ?

///C++   #include<cstring>
///个人比较喜欢用定义string型字符串,有很多方便的功能
  string str1,str2;

2、计算字符串的长度

///利用string 直接得出字符串长度,很方便
   int length1=str1.length();
   int length2=str2.length();

3、比较len1 len2 ,将较小者补位(用0进行部位,位数补到与较大者一致)

 if(length1>=length2)
     for(int i=1; i<=length1-length2; i++) 
      str2 = "0" + str2;
 else
     for(int i=1; i<=length2-length1; i++)  
     str1 = "0" + str1;
     ///把位数补齐时,定义length=str1.length();  
    length1=str1.length(); 

4、进行加法(关键一步)

int nre;  ///该进位后该位的数
int pre=0;  ///储存 进位的变量
 for(int i=length1-1;i>=0;i--){///倒着输出
        nre=str1[i]-'0'+str2[i]-'0'+pre;
        ///将字符数字转换位数字再加上进位的数
        pre=nre/10;  ///进位
        nre%=10;   ///该进位后该位的数
        s=char(nre+'0')+s;   ///强制类型转化
    }
    if(pre!=0) s=char(pre+'0')+s; ///若不为0,则进行存入
    }

5、最后一步来个愉快的输出(会WA的 )就行

最后上总码


#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
#define INF 0x3f3f3f3f
#define MAX_N 555
#define ll long long
int main()
{
    string str,str1,str2;
    int nre;
    int pre=0;
    cin>>str1>>str2;
    int length1=str1.length();
    int length2=str2.length();
    if(length1>=length2)
        for(int i=1; i<=length1-length2; i++)  str2 = "0" + str2;
    else
        for(int i=1; i<=length2-length1; i++)  str1 = "0" + str1;
     ///把位数补齐时,定义length=str1.length();
    length1=str1.length();
    for(int i=length1-1;i>=0;i--){///倒着输出
        nre=str1[i]-'0'+str2[i]-'0'+pre;
        ///将字符数字转换位数字再加上进位的数
        pre=nre/10;  ///进位
        
        nre%=10;   ///该进位后该位的数
        
        str=char(nre+'0')+str;   ///强制类型转化
    }
    if(pre!=0) str=char(pre+'0')+str; ///若不为0,则进行存入

    cout<<str<<endl;
}

**例2、 高精度减法 **

上题
高精度减法

输入输出格式
输入格式:
两个整数a,b(第二个可能比第一个大)

输出格式:
结果(是负数要输出负号)

需注意
1、是两个正数相减,要注意是 大减小,如果是小减大(需要注意从高位借1来减去地位, 比如 18-9 8小于9,不能相减,所以从十位借1来减9,也就是小学减法)
2、

///str1 小于str2 时后相减为负,则只需交换过来,然后相减再取负就行
if(str1.length()<str2.length())  {
     cout<<'-';
     swap(str1, str2);
 }

3、去除多余前导零
这里利用到了c++里面的 STL(StandardTemplate Library),即标准模板库

str.erase( 0 , str.find_first_not_of( '0' ) );
///用来去除我们得出结果中多余的前导0;
 if(!str.length()) ///特判  存在两者相减为零的情况
        cout<<0<<endl;

STL不清楚的可以找一下
度娘

上代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
    string str,str1,str2;
    cin>>str1>>str2;
    if(str1.length()<str2.length())  {
        cout<<'-';
        swap(str1, str2);
    }
    int temp;     ///两数相减后的数 也就是商
    int flag=0;   ///小减大时借位专用
    temp=str1.length()-str2.length();
    for(int i=str2.length()-1; i>=0; i--) {
        if(str1[temp+i] < str2[i]+flag){    ///判断每个位数时 是否 小减大
            ///例如。18-9 8-9小于0,则需要从10位中取1来减去个位中的9
            str=char(str1[temp+i]-str2[i]-flag+'0'+10)+str;  ///小减大的处理方法,加上10,再进上位1,等下一起减掉
            flag=1; ///小减大
        }
        else {
            str=char(str1[temp+i]-str2[i]-flag+'0')+str;  ///大减小,不需要加 10和进位
            flag=0;/// 大减小
        }
    }
    for(int i=temp-1; i>=0; i--) {
        if( str1[i] - flag >= '0') {  /// 道理同上
            str=char(str1[i]-flag)+str; ///强制类型转化
            flag=0;///
        }
        else {
            str=char(str1[i]-flag+10)+str;
            flag=1;
        }
    }
    str.erase(0,str.find_first_not_of('0'));
    ///用来去除我们得出结果中多余的前导0;
    if(!str.length())///特判两者相减为零的情况
        cout<<0<<endl;
    else
    cout<<str<<endl;
}

**例3、 高精度乘法 **

高精度乘法
这次用字符数组来做

关键步骤

1、计算长度

 
 length1=strlen(str1);
 length2=strlen(str2);

2、类型转化

 for(int i=1;i<=length1;++i)
 /// 将字符串转化为整型
   s[i]=str1[length1-i]-'0';
 ///length-i操作是方便后面从低位往高位就行乘法
 for(int i=1;i<=length2;++i)
     ss[i]=str2[length2-i]-'0';

3、从低位开始进行乘法

for(int i=1;i<=length1;++i)
  for(int j=1;j<=length2;++j)
     str[i+j-1]+=(s[i]*ss[j]);
     length=length1+length2;

4、进位操作

 for(int i=1;i<length;++i)
   if(str[i]>9){ ///大于9时则需要进位
       str[i+1]+=str[i]/10; ///进位操作
      str[i]%=10;
       }

5、消除前导零 判断是否相乘为0

 
 while(str[length]==0 && length>1)
          length--; ///消除前导0

6、倒序输出

上代码

#include<bits/stdc++.h>
using namespace std;
#define maxx 50005
char str1[maxx], str2[maxx];///字符数组
int str[maxx];
int s[maxx],ss[maxx];///字符串转化成数字储存的数组
int length,length1,length2;
int main()
{

    cin>>str1>>str2;
    length1=strlen(str1);
    length2=strlen(str2);
    for(int i=1;i<=length1;++i)/// 将字符串转化为整型
        s[i]=str1[length1-i]-'0';///length-i操作是方便后面从低位往高位就行乘法
 for(int i=1;i<=length2;++i)
   ss[i]=str2[length2-i]-'0';
  for(int i=1;i<=length1;++i)
     for(int j=1;j<=length2;++j)
      str[i+j-1]+=(s[i]*ss[j]);///从低位向高位乘
         length=length1+length2;
      for(int i=1;i<length;++i)
       if(str[i]>9){ ///大于9时则需要进位
         str[i+1]+=str[i]/10; ///进位操作
           str[i]%=10;
    }
      while(str[length]==0 && length>1) ///消除前导0
           length--;
    for(int i=length;i>=1;--i)
       cout<<str[i];
     printf("\n");
    return 0;
}

4、高精度除法

1


int comp(int str1[],int str2[]){ ///长度比较
    if(str1[0]>str2[0]) return 1;
    if(str1[0]<str2[0]) return -1;
        for(int i=str1[0];i>0;i--) {///从高位到低位比较
        if(str1[i]>str2[i])   return 1;
        if(str1[i]<str2[i])   return -1;
    }
    return 0;

}

2\ 减法 计算str1=str1-t

 int book;
    book=comp(str1,t);
    if(book==0){/// book等于0,说明两者相等
        str1[0]=0;
        return;
    }
    if(book==1)  {///book等于1,str1>t;
        for(int i=1;i<=str1[0];i++) {///一直提到的借位   若不够向上借位
            if(str1[i]<t[i]) {
                str1[i+1]--;///  借位则减1
                str1[i]+=10;///低位数加10
            }
            str1[i]-=t[i];
        }
        while(str1[0]>0&&str1[str1[0]]==0)///通过判断是否有前导零,删除前导0
            str1[0]--;
        return;
    }


3 进行除法操作


  length=length1-length2+1;
    str[0]=length;
    for(int i=length;i>=1;i--){
        for(int x=1;x<=length2;x++)
            t[i+x-1]=str2[x]; ///将str2赋值到t数组中
            t[0]=length2+i-1;
    while(comp(str1,t)>=0){
        str[i]++; the_subtraction(str1,t);///调用做减法的函数
    }
  }

其他需要的步骤基本于上面所讲的差不多,例如去 前导零等一些必要的操作

上代码

#include<bits/stdc++.h>
using namespace std;
#define maxx 10050
int   str1[maxx],str2[maxx],str[maxx];
char  a[maxx],b[maxx];
int   length,length1,length2,t[maxx];
int comp(int str1[],int str2[]){ ///长度比较
    if(str1[0]>str2[0]) return 1;
    if(str1[0]<str2[0]) return -1;
        for(int i=str1[0];i>0;i--) {///从高位到低位比较
        if(str1[i]>str2[i])   return 1;
        if(str1[i]<str2[i])   return -1;
    }
    return 0;

}
void the_subtraction (int str1[],int t[])
{
    int book;
    book=comp(str1,t);
    if(book==0){/// book等于0,说明两者相等
        str1[0]=0;
        return;
    }
    if(book==1)  {///book等于1,str1>t;
        for(int i=1;i<=str1[0];i++) {///一直提到的借位   若不够向上借位
            if(str1[i]<t[i]) {
                str1[i+1]--;///  借位则减1
                str1[i]+=10;///低位数加10
            }
            str1[i]-=t[i];
        }
        while(str1[0]>0&&str1[str1[0]]==0)///通过判断是否有前导零,删除前导0
            str1[0]--;
        return;
    }
}

int main(){

    cin>>a>>b;int book;
    length1=strlen(a);/// a的长度
    length2=strlen(b);///b的长度
    str1[0]=length1;   ///将str[0]赋值为str1长度方便调用函数时进行值传递
    str2[0]=length2;
    for(int i=1;i<=length1;++i) str1[i]=a[length1-i]-'0';
    ///类型转化将字符串转化为整型数
    for(int i=1;i<=length2;++i) str2[i]=b[length2-i]-'0';
    length=length1-length2+1;
    str[0]=length;
    for(int i=length;i>=1;i--){
        for(int x=1;x<=length2;x++)
            t[i+x-1]=str2[x]; ///将str2赋值到t数组中
            t[0]=length2+i-1;
    while(comp(str1,t)>=0){
        str[i]++; the_subtraction(str1,t);///调用做减法的函数
    }
  }

    while(length>0 && str[length]==0) length--; ///去掉前导0
    if(length==0) ///大除小则为0
        printf("0");
    else
        for(int i=length;i>=1;i--)
        printf("%d",str[i]);

    printf("\n");
return 0;
}



好了,这次的高精度算法已经讲完了,高精度算法可以用很多不同种代码去实现,我用的只是其中的一种,嘻嘻
若有错误,麻烦指出来,一起交流,一起进步
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42878218/article/details/96006909
今日推荐