从此搞定高精度运算,超详细讲解

本文出自我的掘金博客, 欢迎大家访问!

  • 一开始其实是用java写算法的, 后来由于某些原因又成了一名C++选手, 高精度的题目本来可以用java的高精度运算类水过去, 但为了自己的编码能力着想, 还是用C++的数组实现了一遍高精度运算, 下面我将认真的整理一下具体应该怎样用C++实现高精度运算(主要还是来源于几个大牛写的题解, 我自己写的基本代码丑且难看555QwQ)

高精度加法

要点: 首先要将低位放在数组的头部, 其次就是要注意进位, 然后就是模仿小学的列竖式计算喽!

这里强调一下预处理的步骤, 即读入这么一个大数, 你可以用C++中的string, 也可以用c中的char []数组, 其实都是一样的, 感觉我自己没有讲清楚, 我还是来给一给具体的实现作一下参考吧.

//用string
string str1, str2;
cin >> str1 >> str2;
这时你已经将这两个数以字符串的形式存起来了, 然后你就可以从字符串的最后面进行计算
string add(string str1,string str2)//高精度加法
{
    string str;
    int len1=str1.length();
    int len2=str2.length();
    //前面补0,弄成长度相同
    if(len1<len2)
    {
        for(int i=1;i<=len2-len1;i++)
           str1="0"+str1;
    }
    else
    {
        for(int i=1;i<=len1-len2;i++)
           str2="0"+str2;
    }
    len1=str1.length();
    int cf=0;
    int temp;
    for(int i=len1-1;i>=0;i--)
    {
        temp=str1[i]-'0'+str2[i]-'0'+cf;
        cf=temp/10;
        temp%=10;
        str=char(temp+'0')+str;
    }
    if(cf!=0)  str=char(cf+'0')+str;
    return str;
}
  • 第二种借助于char []数组的写法我更推荐一些
char a[50001], a1[50001];
cin >> a1;
a[0] = strlen(a1);
for (int i = 1; i <= a[0]; i++) {
    a[i] = a1[a[0] - i] - '0';
}

高精度减法

对于高精度减法而言就要复杂很多, 首先你得考虑可能是一个小数减去一个大数的问题, 其次你得考虑借位的问题, 最后你要考虑去除前导0的问题, 比如10001 - 10000 = 00001你得去除这几个前导0, 最后, 你还得注意0 应该输出0;
#include <bits/stdc++.h>

using namespace std;
int a[10100], b[10100], res[10100], maxl;
bool flag = false;//这个是同来标记是否需要加负号

//这个函数的作用是用来判断减数与被减数谁大
int cmp (string str1, string str2) {
    if (str1.length() > str2.length()) {
        return 1;
    } else if (str1.length() < str2.length()) {
        return -1;
    } else {
        return str1.compare(str2);
    }
}

string sub(string str1, string str2) {
    string str;
    int cf = 0; //用来标记是否借位
    int tmp = str1.length() - str2.length();

    for (int i = str2.length() - 1; i >= 0; i--) {
        if (str1[tmp + i] < str2[i] + cf) {
            str = char(str1[tmp + i] - str2[i] - cf + '0' + 10) + str;
            cf = 1;
        } else {
            str = char(str1[tmp + i] - str2[i] - cf + '0') + str;
            cf = 0;
        }
    }

    for (int i = tmp - 1; i >= 0; i--) {
        if (str1[i] - cf >= '0') {
            str = char(str1[i] - cf) + str;
            cf = 0;
        } else {
            str = char(str1[i] - cf + 10) + str;
            cf = 1;
        }
    }
    str.erase(0,str.find_first_not_of('0'));//去除结果中多余的前导0
    return str;
}

int main() {
    string a;
    string b;
    cin >> a >> b;

    if (cmp(a, b) == 0) {
        cout << 0 << endl;
    } else if (cmp(a, b) < 0) {
        swap(a, b);
        cout << '-' << sub(a, b) << endl;
    } else {
        cout << sub(a, b) << endl;
    }

    return 0;
}

高精度乘法

这个需要注意的地方也是前导0和进位而已, 这里介绍一个下处理技巧, 考虑我们平时的竖式乘法, 我们会发现对于乘数1的第i位与乘数2的第j位相乘会对结果的第i + j - 1位作出贡献, 这么说吧, 结果的第k位是两个乘数的第ij位(满足i + j - 1 == k)作出贡献(先不考虑进位的问题)用代码描述是这样的

for (i=1;i<=a[0];++i)for (j=1;j<=b[0];++j)c[i+j-1]+=a[i]*b[j];

考虑进位后整体的代码是这样的

#include<iostream>
#include<cstring>
using namespace std;
char a1[50001],b1[50001];
int a[50001],b[50001],i,x,len,j,c[50001];
int main ()
{
    cin >>a1 >>b1;//读入两个数
    a[0]=strlen(a1);b[0]=strlen(b1);//计算长度
    for (i=1;i<=a[0];++i)a[i]=a1[a[0]-i]-'0';//将字符串转换成数字
    for (i=1;i<=b[0];++i)b[i]=b1[b[0]-i]-'0';
    for (i=1;i<=a[0];++i)for (j=1;j<=b[0];++j)c[i+j-1]+=a[i]*b[j];//按乘法
    len=a[0]+b[0];                                       //原理进行高精乘
    for (i=1;i<len;++i)if (c[i]>9){c[i+1]+=c[i]/10;c[i]%=10;}//进位
    while (c[len]==0&&len>1)len--;//判断位数
    for (i=len;i>=1;--i)cout <<c[i];//输出
    return 0;
}

上述代码来源于神犇的题解, 蒟蒻仅作整理, 希望能帮助您!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值