大数运算

int类型一般4字节,long类型一般8字节,最长都不能超过8字节=64位,因为cpu中的寄存器最长64位(希望没说错),所以64位以上的数据运算就需要特殊处理了。
首先定义下:a,b均为自然数,任何加减法都能在下表归类

类型等价于方法
a+ba+b加法
(-a)+bb-a减法
a+(-b)a-b减法
(-a)+(-b)-(a+b)加法

说明:以下代码头文件均为

#include <bits/stdc++.h>
using namespace std;

大数加法

思路:对应位相加,用进位记录器flag记录是否有进位:

string string_add(string a, string b)
{
//默认两个正数相加
    if (a.size() == 0)
        return b;
    if (b.size() == 0)
        return a;
    if (a.size() < b.size())
    {
        return string_add(b, a);
    }
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    string ret = "";
    bool flag = 0;
    for (int i = 0; i < a.size(); i++)
    {
        int n;
        if (i >= b.size())
        {
            n = a[i] - '0' + flag;
        }
        else
        {
            n = a[i] - '0' + b[i] - '0' + flag;
        }
        ret += (n % 10 + '0');
        flag = n / 10;
    }
    if (flag == 1)
        ret += '1';
    reverse(ret.begin(), ret.end());
    return ret;
}

大数减法

首先保证参数a,b都是正数,形式为a-b,其中a>b。若a<b,递归即可。其中数据转字符部分,什么时候加’0’什么时候减’0’,得分清楚,我在这debug了一会。

bool is_first_bigger(string a, string b)
{
    if (a.size() > b.size())
        return 1;
    else if (a.size() < b.size())
        return 0;
    else
    {
        for (int i = 0; i < a.size(); i++)
        {
            if (a[i] < b[i])
                return 0;
        }
        return 1;
    }
}
string string_sub(string a, string b)
{
    if (b.size() == 0)
        return a;
    if (!is_first_bigger(a, b))
    {
        //只处理a>=b的情况
        return '-'+string_sub(b, a);
    }
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    string ret = "";
    bool flag = 0;
    for (int i = 0; i < a.size(); i++)
    {
        int n;//n是每位的运算结果
        if (i >= b.size())
        {
            n = a[i] -'0'- flag;
            flag = 0;
        }
        else
        {
            if (a[i] >= b[i])
            {
                n = a[i] - b[i] - flag;
                flag = 0;
            }
            else
            {
                n = a[i] + 10 - b[i] - flag;
                flag = 1;
            }
        }
        ret += (char)(n + '0');
    }
    reverse(ret.begin(), ret.end());
    return ret;
}

大数乘法

思路,对于111*123,我们按步骤算111*3、111*2、111*1,也就是b的每位乘以a全部,再把他们结果补相应位数的0,加起来。而111*3这类有一个乘数为1位的乘法容易实现一点,称为简单乘法。其他乘法均能分解成若干个简单乘法的结果之和。
这里我默认两个参数为正数,为负数时调用自身加负号即可(偷懒没写)。

string string_times(string a, string b)
{
    if (a.size == 0 and a[0] == '0' or b.size == 0 and b[0] == '0')
       return "0";
    //我们只处理a.size>=b.size
    if (a.size() < b.size())
    {
        return string_times(b, a);
    }
    string ret = "";
    if (b.size() == 1)
    {//111*3 容易计算 称为简单乘法
        int flag = 0;
        for (int i = a.size() - 1; i >= 0; i--)
        {
            int n = (a[i] - '0') * (b[0] - '0') + flag;
            flag = n / 10;
            ret += (n % 10 + '0');
        }
        if (flag != 0)
        {
            ret += (flag + '0');
        }
        reverse(ret.begin(), ret.end());
    }
    else
    {//111*123不容易计算,分解成3个简单乘法相加
        int p = b.size() - 1;
        for (auto i : b)
        {
            string s = "";
            s = string_times(a, s + i);
            for (int i = 0; i < p; i++)
            {
                s += '0';
            }
            p--;
            ret = string_add(ret, s);
        }
    }
    return ret;
}

大数除法

有点复杂,挖个坑哈,以后可能来填。😁

总结

这几个大数运算我拖了2天没做,以为很难总不敢去写。今晚静下心来写完了,发现也没那么难,模拟手算就行了。所以说编码,要耐心下来,一步一步来,最好先想明白再动手敲代码,奥力给!!
I❤coding

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值