• 【常用算法总结——C++高精度运算】


      众所周知,数与数进行运算时,当两个数位数过大,我们的电脑就会烤鱼。所以我们就出现了高精度运算,他的思想主要就是用字符串来存储数据,再一位一位地分别计算(因为是字符,所以要记得-‘0’或-48),达到最后的结果。所以,这篇文章将会告诉大家如何进行C++中的一些高精度运算。

    如果有没写的,说明博客主智商阅历不够,以后就会有了(等着吧)

    高精度加法

      一位一位的对着加,注意存储进位,小的数加完后把大数剩下的加进来,注意前导零和相加等于0

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int c[10000001];//记录结果的数组 
     4 string a,b;
     5 long long k=0,r=0,i,j;
     6 bool flag;
     7 int main()
     8 {
     9     cin>>a>>b;//输入需要做操作的字符串 
    10     if(a.size()<b.size()||a.size()==b.size()&&a<b)//把大的字符串放前面,方便操作 
    11     {
    12         swap(a,b);
    13     }
    14     for(i=a.size()-1,j=b.size()-1;j>=0;i--,j--)//从最低位相加,相加他们的公共部分,所以j>=0 
    15     {
    16         c[k++]=(r+a[i]-'0'+b[j]-'0')%10;//两个位数和进位的相加后取个位 
    17         r=(r+a[i]-'0'+b[j]-'0')/10;//记录进位 
    18     }
    19     while(i>=0)//再把剩下的继续加 
    20     {
    21         c[k++]=(r+a[i]-'0')%10;//位数和进位的相加后取个位 
    22         r=(r+a[i]-'0')/10;//记录进位 
    23         i--;
    24     }
    25     if(r)c[k++]=r;//如果还有进位,进到最高位 
    26     for(i=k-1;i>=0;i--)//输出 
    27     {
    28         if(c[i]!=0||flag)//防止前导0输出的操作 
    29         {
    30             cout<<c[i];
    31             flag=true;
    32         }
    33     }
    34     if(flag==false)cout<<0;//如果都没有输出,说明相加结果为0,应当输出0 
    35     return 0;
    36 }

    以上代码是两个正数相加,若有负数,则需要另行判断:

      如果两个数都是负数,那么去掉负号,输出结果前加上负号即可。

      如果两个数有一个数是负数,先去掉负号,比较大小

        如果去掉负号的数大于另一个数,则需要用去掉负号的数减去另一个数,再输出负号(此时用高精度减法)

        如果去掉负号的数小于另一个数,则需要用另一个数减去去掉负号的数,(此时用高精度减法)

    高精度减法

      一位一位的对着减,注意存储借位,小的数减完后把大数剩下的借位减进来,注意前导零和相减等于0

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int c[10000001];//记录结果的数组 
     4 string a,b;
     5 long long k=0,r=0,i,j;
     6 bool flag;
     7 int main()
     8 {
     9     cin>>a>>b;//输入需要做操作的字符串
    10     if(a.size()<b.size()||a.size()==b.size()&&a<b)//把大的字符串放前面,方便操作 ,还要判断相减是否为负数 
    11     {
    12         cout<<"-";
    13         swap(a,b);
    14     }
    15     for(i=a.size()-1,j=b.size()-1;j>=0;i--,j--)
    16     {
    17         c[k++]=(a[i]-b[j]-r);//两个位数相减再减去接的位数 
    18         r=0;//清零标记 
    19         if(c[k-1]<0){c[k-1]+=10;r=1;}//如果是负数就借十,并标记 
    20     }
    21     while(i>=0)剩下的继续减 
    22     {
    23         c[k++]=(a[i]-'0'-r);//减去借的 
    24         r=0;//清零标记 
    25         if(c[k-1]<0){c[k-1]+=10;r=1;}//如果是负数就借十,并标记 
    26         i--;
    27     }
    28     for(i=k-1;i>=0;i--)//输出 
    29     {
    30         if(c[i]!=0||flag)//防止前导0输出的操作 
    31         {
    32             cout<<c[i];
    33             flag=true;
    34         }
    35     }
    36     if(flag==false)cout<<0;//如果都没有输出,说明相减结果为0,应当输出0 
    37     return 0;
    38 }

    以上代码是两个正数相减,若有负数,则需要另行判断:

      如果两个数都是负数,去掉负号,用后一个数减前一个数。

      如果两个数有一个数是负数,先去掉负号,比较大小

        如果第一个数是负数,相加,输出负号(此时用高精度加法)

        如果第二个数是负数,相加(此时用高精度加法)

    高精度乘法

      相信大家都手动计算过乘法,就是一个数的每一位乘另一个数的每一位最后相加即可,当然,我们程序也是这样模拟

      这里有一个基本的知识点,相信大家在手写竖式的时候知道,就是c[i+j]+=a[i]+b[j](因为a和b都是从0下标开始的,如果从下标1开始,就c[i+j-1]+=a[i]+b[j])

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 string a,b;
     4 int k;
     5 int c[1000001];
     6 int main()
     7 {
     8     cin>>a>>b;
     9     reverse(a.begin(),a.end());
    10     reverse(b.begin(),b.end());
    11     for(int i=0;i<a.size();i++)
    12     {
    13         for(int j=0;j<b.size();j++)
    14         {
    15             c[i+j]+=(a[i]-48)*(b[j]-48);
    16         }
    17     }
    18     for(k=0;k<=a.size()+b.size();k++)
    19         c[k]+=c[k-1]/10,c[k-1]%=10;
    20     while(!c[k]&&k>=1)k--;
    21     for(;k>=0;k--)
    22         cout<<c[k];
    23     return 0;
    24 }

    高精度除法(高精除以高精)

    高精度除法(高精除以低精)

      手动模拟除法过程,每次读到新位计算出被除数,然后计算。大体就是一位一位的做减法操作。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int c[10000001];//记录结果的数组 
     4 string s;
     5 long long k=0,a,b,i;
     6 bool flag;
     7 int main()
     8 {
     9     cin>>s>>b;//输入被除数和除数 
    10     for(int i=0;i<s.size();i++)//从高位开始,一位一位向低位 
    11     {
    12         a=a*10+s[i]-'0';//加上被除数的这一位 
    13         c[k++]=a/b;
    14         a%=b;//除完了 
    15     }
    16     for(i=0;i<k;i++)//因为是从高位到低位,所以要反着输出 
    17     {
    18         if(c[i]!=0||flag)//防止前导0输出的操作 
    19         {
    20             cout<<c[i];
    21             flag=true;
    22         }
    23     } 
    24     if(flag==false)cout<<1;//如果都没有输出,说明相减结果为1,应当输出1 
    25     return 0;
    26 }

    以上代码是两个正数相除,若有负数,则需要另行判断:

      如果两个数都是负数,去掉负号,不管他。

      如果两个数有一个数是负数,去掉负号,输出时加上。

    高精度模运算(高精模低精)

      这个和高精度除法差不多,不需要记录和输出商就差不多

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 string s;
     4 long long k=0,a,b,i;
     5 bool flag;
     6 int main()
     7 {
     8     cin>>s>>b;//输入被除数和除数 
     9     for(int i=0;i<s.size();i++)//从高位开始,一位一位向低位 
    10     {
    11         a=a*10+s[i]-'0';//加上被除数的这一位 
    12         a%=b;//一直取余 
    13     }
    14     cout<<a; 
    15     return 0;
    16 }

    高精度开根

  • 相关阅读:
    14-快速排序
    linux上挂在windows的共享文件系统,大小写不敏感
    【mount】linux挂共享盘
    监控windows服务或者进程
    自定义时间间隔
    示例
    filebeat
    kafka
    文档碎片
    简单DOM操作
  • 原文地址:https://www.cnblogs.com/hualian/p/11176572.html
Copyright © 2020-2023  润新知