大数运算(C++)

大数就是指十几位,几十位或者几百位的数字,反正对于这样的数,任何计算机本身的变量类型(int,double,甚至long long)都表示不了。怎么存?最常用的就是用字符串string或者向量vector,然后的问题自然是要实现大数的四则运算。

大数加法

加法的实现很简单,就是从低位开始,模拟加法的计算过程,需要注意的就是计算过程中产生的进位。
string实现大数加法:

string BigIntPlus(string s1, string s2)
{
    //把较长的数给s1,方便写程序
    if (s1.size() < s2.size())
    {
        string tmp = s2;
        s2 = s1;
        s1 = tmp;
    }
    //从低位开始,模拟加法的过程,注意每次加法的进位即可
    for (int i = s1.size()-1, j = s2.size()-1; i >= 0; i--, j--)
    {
        s1[i] = s1[i] + (j >= 0 ? s2[j] - '0' : 0);
        if (s1[i] > '9')//表示有进位
        {
            s1[i] -= 10;
            if (i) s1[i - 1]++;
            else s1 = '1' + s1;//i=-1,表示超过了原来的长度,利用字符串加法
        }
    }
    return s1;
}

大数减法

大数减法虽然看起来也就是模拟做减法的过程,但实际上比加法复杂的多。网上很多所谓的大数减法的程序,要么只能计算结果为正数的情况,要么2225-2227算下来结果显示-0002,什么鬼嘛,等于-2呀。
1.string实现大数减法:

//用来清除数字字符串前多余的0
string eraseZero(string s)
{
    if (s.size() <= 1) return s;
    if (*s.begin() != '0') return s;
    s.erase(s.begin());
    return eraseZero(s);
}
//返回s1-s2的值
//为了方便写程序,我们先保证计算的结果是正数,最后看情况是否需要转负数
string BigIntMinus(string s1, string s2)
{
    bool tag = false;//用来标记s1 s2是否发生了交换
    if (s1.size() < s2.size() || (s1.size()==s2.size() && s1 < s2))
    {
        tag = true;
        string tmp = s2;
        s2 = s1;
        s1 = tmp;
    }
    for (int i = s1.size()-1, j = s2.size()-1; i >= 0; i--, j--)
    {
        if (j>=0){
            if (s1[i] < '0' || s1[i] < s2[j])//需要借位
            {
                s1[i] = s1[i] + 10 - ((j < 0) ? 0 : s2[j] - '0');
                s1[i - 1]--;
                continue;
            }
        }
        s1[i] = s1[i] - ((j<0) ? 0 : s2[j] - '0');
    }
    //处理计算结果字符串前面多余的0,比如0005应该显示5
    string result = eraseZero(s1);
    if (tag) result = '-' + result;
    return result;
}

虽然我们用string可以实现大数减法,但写程序的过程总是很不舒服的。因为我们从头到尾都要记得我们处理的是字符’0’…..’9’,而不是真正的数字0,1……9。

大数乘法

大数的乘法就有多种算法思想。主要有分治法、快速傅里叶变换FFT法、中国剩余定理、简单方法(模拟乘法的过程)。前面几种看起来就NB,被吓住的赶紧去百度一下,我这里还是简单研究下简单方法……

这里我们从LeetCode的一道题目说起:Multiply Strings
这里写图片描述
这里我直接贴高票答案的代码,因为实在写的太好了,我自己写的不堪入目。

string multiply(string num1, string num2) {
    string sum(num1.size() + num2.size(), '0');

    for (int i = num1.size() - 1; 0 <= i; --i) {
        int carry = 0;
        for (int j = num2.size() - 1; 0 <= j; --j) {
            int tmp = (sum[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0') + carry;
            sum[i + j + 1] = tmp % 10 + '0';
            carry = tmp / 10;
        }
        sum[i] += carry;
    }

    size_t startpos = sum.find_first_not_of("0");
    if (string::npos != startpos) {
        return sum.substr(startpos);
    }
    return "0";
}

GMP

其实关于大数运算,早就有高精度计算库GUN的GMP(Arithmetic without limitations)
GMP,我们只需要调用就行了。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值