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