C++:高精度运算复习(加|减|乘|除法)

C++11 代码,用 string 类存储及运算
所有函数都已经过测试,没有错误,性能大家自己评判~

1.高精度加法

  • 输入为两个非负数
string BigIntergerAdd(const string &a, const string &b)
{
    if (a.size() < b.size())
        return BigIntergerAdd(b, a);
    string ans;
    auto i = a.rbegin(), j = b.rbegin();
    bool sp = false;
    while (j != b.rend())
    {
        auto temp = (*i - '0') + (*j - '0');
        if (sp)
            ++temp;
        sp = false;
        if (temp >= 10)
        {
            sp = true;
            temp -= 10;
        }
        ans.push_back(temp + '0');
        ++i, ++j;
    }
    while (i != a.rend())
    {
        auto temp = (*i - '0');
        if (sp)
            ++temp;
        sp = false;
        if (temp >= 10)
        {
            sp = true;
            temp -= 10;
        }
        ans.push_back(temp + '0');
        ++i;
    }
    if (sp)
        ans.push_back('1');
    reverse(ans.begin(), ans.end());
    return ans;
}
  • 逐位相加 push_back ,倒置字符串后返回。

2.高精度减法

  • 输入为两个非负数
string BigIntergerSub(const string &a, const string &b)
{
    if (a.size() < b.size() || (a.size() == b.size() && a < b))
        return "-" + BigIntergerSub(b, a);
    if (a == b)
        return string("0");
    string ans;
    auto i = a.rbegin(), j = b.rbegin();
    bool sp = false;
    while (j != b.rend())
    {
        auto temp = (*i - '0') - (*j - '0');
        if (sp)
            --temp;
        sp = false;
        if (temp < 0)
        {
            sp = true;
            temp += 10;
        }
        ans.push_back(temp + '0');
        ++i, ++j;
    }
    while (i != a.rend())
    {
        auto temp = (*i - '0');
        if (sp)
            --temp;
        sp = false;
        if (temp < 0)
        {
            sp = true;
            temp += 10;
        }
        ans.push_back(temp + '0');
        ++i;
    }
    reverse(ans.begin(), ans.end());
    return ans.substr(ans.find_first_not_of('0'));
}
  • 通过判断长度和字典序大小决定哪个字符串中的数较大,保证用较大的数减去较小的数。

3.高精度乘法

  • 输入为两个非负整数
string BigIntergerMul(const string &a, const string &b)
{
    if (a == "0" || b == "0")
        return "0";
    string ans(a.size() + b.size(), '0');
    int sp = 0;
    for (auto i = a.rbegin(); i != a.rend(); ++i)
    {
        if (*i == '0')
            continue;
        auto aimi = (*i - '0');
        auto spindex = (i - a.rbegin());
        for (auto j = b.rbegin(); j != b.rend(); ++j)
        {
            auto temp = ans[spindex] - '0' + aimi * (*j - '0') + sp;
            sp = 0;
            if (temp >= 10)
            {
                sp = temp / 10;
                temp -= sp * 10;
            }
            ans[spindex++] = temp + '0';
        }
        while (sp)
        {
            ans[spindex++] += sp % 10;
            sp /= 10;
        }
    }
    reverse(ans.begin(), ans.end());
    return ans.substr(ans.find_first_not_of('0'));
}
  • 预置结果字符串大小为最大可能(两个乘数长度之和),最后翻转字符串后去除前置零。

4.高精度除法

  • 输入为两个非负整数,返回两个整数,商和余数
using pairstring = pair<string, string>;
pairstring BigIntergerDiv(const string &consta, const string &b)
{
    if (b == "0")
        return {"ERROR", "DIV 0"};
    if (consta.size() < b.size() || (consta.size() == b.size() && consta < b))
        return {"0", consta};
    string a = consta, s;
    int beg = 0, asize = a.size(), bsize = b.size();
    bool isbeg = false;
    for (int ed = b.size() - 1; ed != asize; ++ed)
    {
        int temp = 0;
        while (ed - beg + 1 > bsize || (ed - beg + 1 == bsize && a.compare(beg, ed - beg + 1, b) >= 0))
        {
            ++temp;
            int j = ed;
            bool isp = false;
            for (auto k = b.rbegin(); k != b.rend(); ++k)
            {
                a[j] -= *k - '0';
                if (isp)
                    --a[j];
                isp = false;
                if (a[j] < '0')
                {
                    isp = true;
                    a[j] += 10;
                }
                --j;
            }
            while (isp)
            {
                --a[j];
                isp = false;
                if (a[j] < '0')
                {
                    isp = true;
                    a[j] += 10;
                }
                --j;
            }
            while (beg <= ed && a[beg] == '0')
                ++beg;
        }
        while (beg <= ed && a[beg] == '0')
            ++beg;
        if (!isbeg && temp)
            isbeg = true;
        if (isbeg)
            s.push_back(temp + '0');
    }
    if (beg == asize)
        return {s, "0"};
    return {s, a.substr(beg, asize - beg + 1)};
}

在满足可以相减的位置开始,循环减去除数,直到当前位置小于除数。循环这个操作直到被除数扫描完毕。
需要特判被除数比除数小、除数是 0 的情况。
 
 

END

你可能感兴趣的:(C/C++)