高精度加减

1 高精度加法

主要有以下几步:

  1. 输入处理:使用字符串来存储大整数,避免数值范围限制。
  2. 对齐数字:确保两个数字的数位对齐(前面补零)。
  3. 逐位相加:从最低位开始,逐位相加并处理进位。
  4. 最高进位:在最后检查是否有剩余进位。
  5. 结果反转:因为是从低位开始计算,所以最后需要反转字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int a[N], b[N], c[N];  // 方便进位和数位对齐的逆序整型数组
void addBigNumber(string num1, string num2) {
// 计算长度
int len1 = num1.length(), len2 = num2.length();
// 逆序存储到整型数组
for(int i = 0; i < len1; i++) a[i] = num1[len1 - 1 - i] - '0';
for(int i = 0; i < len2; i++) b[i] = num2[len2 - 1 - i] - '0';

// 循环较长数字的位数
int len = max(len1, len2);
for(int i = 0; i < len; i++) {
c[i] += a[i] + b[i]; // 这一位加上两个数的和
c[i + 1] += c[i] / 10; // 这一位超过10进位到下一位
c[i] %= 10; // 这一位超过10要取余
}

if(c[len]) len++; // 如果最高位有进位,长度加1

for(int i = len - 1; i >= 0; i--) cout << c[i]; // 逆序输出
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
string addBigNumber(string num1, string num2) {
// 分别计算两数的最后一位数下标,并初始化进位
int i = num1.size() - 1, j = num2.size() - 1, carry = 0;

string res;
// 只要有数字没加完 或 有进位没处理就继续运算
while(i >= 0 || j >= 0 || carry) {
int sum = carry; // 这一位的结果先赋为进位值
if(i >= 0) sum += num1[i--] - '0'; // 第一个数没加完就加
if(j >= 0) sum += num2[j--] - '0'; // 第二个数没加完就加

carry = sum / 10; // 计算是否有进位
res += sum % 10 + '0'; // 对10取余处理进位
}
reverse(res.begin(), res.end()); // 翻转答案

return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
string addBigNumber(string num1, string num2) {
// 确保 num1 是较长的数字
if(num1.length() < num2.length()) swap(num1, num2);

string res; // 最终答案
int carry = 0; // 进位,初始为0
int len1 = num1.length(), len2 = num2.length(); // 长度

// 从最低位开始相加,加到较长数字的位数
for(int i = 0; i < len1; i++) {
// 较长数字正常 -'0' 转化为 int 即可
int digit1 = num1[len1 - 1 - i] - '0';
// 如果超出了较短数字的位数,默认补0即可
int digit2 = i < len2 ? num2[len2 - 1 - i] - '0' : 0;

// 这一位的总和等于:两数相加并加上进位
int sum = digit1 + digit2 + carry;
carry = sum / 10; // 下一位的进位等于这一位总和对10整除
res += sum % 10 + '0'; // 最终这一位的结果要对10取余,并且恢复为字符串
}

// 如果还有进位,说明最高位也发生了进位,超出了原有最长位数,要单独处理
if(carry) res += carry + '0';

// 由于前面是从最低位开始加的,这里要对结果进行翻转
reverse(res.begin(), res.end());

return res;
}

2 高精度减法

主要有以下几步

  1. 比较大小:比较两个数字字符串的大小,确定减数和被减数,并标记负号。
  2. 对齐数字:确保两个数字的数位对齐(前面补零)。
  3. 逐位相减:从最低位开始,逐位相减并处理借位。
  4. 结果处理:移除结果中的前导零,判断是否添加负号。
  5. 结果反转:因为是从低位开始计算,所以最后需要反转字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
string subBigNumber(string num1, string num2) {
char op = ' '; // 记录符号
// 确保 num1 > num2,否则记录负号并交换
if(num1.size() < num2.size() || num1.size() == num2.size() && num1 < num2) {
op = '-';
swap(num1, num2);
}

string res; // 最终答案
int borrow = 0; // 借位,初始为0
int len1 = num1.size(), len2 = num2.size(); // 长度

// 运算按较长数字的长度
for(int i = 0; i < len1; i++) {
// 较长数字正常 -'0' 转化为 int 即可
int digit1 = num1[len1 - 1 - i] - '0';
// 如果超出了较短数字的位数,默认补0即可
int digit2 = i < len2 ? num2[len2 - 1 - i] - '0' : 0;

// 这一位的结果等于:两数相减并减去借位
int dif = digit1 - digit2 - borrow;
// 判断是否需要借位
if(dif < 0) borrow = 1;
else borrow = 0;
// 这一位的结果先加10再取余,可以处理需要借位的负数,并 + '0' 转字符
res += (dif + 10) % 10 + '0';
}

// 处理前导0,但注意保留一个,因为结果可能为0
while(res.size() > 1 && res.back() == '0') res.pop_back();

// 处理负号
if(op == '-') res += '-';

// 翻转字符串
reverse(res.begin(), res.end());

return res;
}

高精度加减
http://example.com/2025/10/29/coding/C++与算法/高精度/高精度加减/
作者
baoduozhu
发布于
2025年10月29日
许可协议