高精度加法
2026-06-11 20:25:52
发布于:浙江
【模板+详解】 高精度加法
嗯...
首先让我们引入高精度这个东西....
相信大家都会做A+B Problem 这道题....输出的是A+B 的值....
可你想过没有,如果 A = 5983461827658923256597314923593449492545242655621498167329758256231975822594359252779832914372582828292235591346798922923,
B = 9382872892382859234389628259232359438768953797679368296159683689865328523725925829753298653219197389235498228659659373291973652564256594,
而这时,所有的类型都无法存储A和B这两个数....而这时,高精度就要出马了...(附图关于数据类型范围....)
| 数据类型 | 定义标识符 | 占字节数 | 数值范围 | 数量级表示 |
|---|---|---|---|---|
| 短整型 | short [int] | 2 (16位) | -32768 ~ 32767 | -2^15 ~ 2^15-1 |
| 整型 | [long] int | 4 (32位) | -2147483648 ~ 2147483647 | -2^31 ~ 2^31-1 |
| 长整型 | long [int] | 4 (32位) | -2147483648 ~ 2147483647 | -2^31 ~ 2^31-1 |
| 超长整型 | long long [int] | 8 (64位) | -9223372036854775808 ~ 9223372036854775807 | -2^63 ~ 2^63-1 |
| 无符号整型 | unsigned [int] | 2 (16位) | 0 ~ 65535 | 0 ~ 2^16-1 |
| 无符号短整型 | unsigned short [int] | 2 (16位) | 0 ~ 65535 | 0 ~ 2^16-1 |
| 无符号长整型 | unsigned long [int] | 4 (32位) | 0 ~ 4294967295 | 0 ~ 2^32-1 |
| 无符号超长整型 | unsigned long long | 8 (64位) | 0 ~ 18446744073709551615 | 0 ~ 2^64-1 |
这里首先讲的是高精度的加法。下面是一个伪代码,主要表达了高精度加法的主要流程:
伪代码—流程
1. read(); // 读入两个大整数
2. calsum(); // 求和
3. print(); // 输出结果
Question 1:
这么大的数,如何进行读入?
Answer 1:
当输入的数很大时,可采用字符串方式接收。输入要符合整数的输入规则:连续输入每位数字,中间无空格。
在这里会牵扯到另一部分的知识——字符串...其实字符串还是比较常用的...
下面就简单提几方面:
Part 1:
字符串定义方式:
string s; // 直接定义
char s[1007]; // 用一个字符数组模拟字符串,这种的灵活性与速度上有优势
不同方式定义的字符串,对应的函数也不同。如 string s; 则 len = s.length(); 而 char s[1007]; 则 len = strlen(s);
Part 2:
字符串的读入:
这里主要介绍三种方式:1. cin 2. scanf 3. gets
下面给大家演示一下它们的具体的读入方法:
1. cin:
string s1, s2;
cin >> s1 >> s2;
int lena = s1.length();
int lenb = s2.length();
cout << s1 << " " << s2 << endl;
cout << lena << " " << lenb;
2. scanf://输入的两个字符串:可以在同一行,中间以空格隔开。也可以各占一行。
char s1[1010], s2[1010];
int main()
{
scanf("%s%s", s1, s2); // scanf("%s%s",&s1,&s2); &可省略
int lena = strlen(s1); // strlen()函数需要头文件cstring
int lenb = strlen(s2);
cout << s1 << " " << s2 << endl;
cout << lena << " " << lenb;
}
3. gets://输入的两个字符串必须各占一行
char s1[1010], s2[1010];
gets(s1);
gets(s2);
lena = strlen(s1);
lenb = strlen(s2);
注意:
scanf、cin遇空格或回车符则认为当前字符串结束
gets遇回车符则认为当前字符串结束
Question 2:
我们将读入的数作为字符串接收了进来,可是怎么进行加减乘除等数学运算呢?
Answer 2:
拆成一位一位的数字,把它们存在一个数组中,一个数组元素表示一位数字……解释:“拆”
例如:123 拆成 a[1]=3, a[2]=2, a[3]=1
详细过程:——字符串读入,数组保存(见代码)
//利用字符串函数和操作运算,将每一位数取出,存入数组中。
//假设已经利用字符串s读取数据
lena = s.length(); //用lena存放字符串s的位数
for(i = 1; i <= lena; i++)
a[i] = s[lena - i] - '0'; //将数串s转换为数组a,注意:倒序存储
解释倒序保存的原因:
在平常,数字从左到右依次为从高位到低位....可这里却与日常的习惯相反。因为在存储时我们首先能确定的就是最低位,所以设它为第一位,而高位无法确定,因为在存储之前求出字符串的长度比较麻烦,所以我们用下标较大的数组存储高位,因为它的最高位无法确定....
Question 3:
两个高精度数已经分别保存在数组a和b中,下一步,应该如何求和?
Answer 3:
用到了小学所学的“竖式计算”的思想:
运算的次数为:max(lena, lenb)
程序实现:
方法一:
模拟手工计算,设置一个进位变量m,但是此方式比较麻烦:
for (int i = 1; i <= lena; i++)
a[i] = s1[lena - i] - 48; // 由字符转向真正意义的数字 ,并且为倒序
for (int i = 1; i <= lenb; i++)
b[i] = s2[lenb - i] - 48; // 同上
lenc = max(lena, lenb);
for (int i = 1; i <= lenc; i++)
{
c[i] = (m + a[i] + b[i]) % 10;
m = (m + a[i] + b[i]) / 10; // 进位
}
if (m) { // 判断最高位是否需要进位
lenc++;
c[lenc] = 1;
}
方法二:
先计算,最后处理进位,比方法一要简单:
for (int i = 1; i <= lenc; i++)
c[i] = a[i] + b[i]; // 先计算
for (int i = 1; i <= lenc; i++)
{
c[i + 1] = c[i + 1] + c[i] / 10;
c[i] = c[i] % 10; // 后处理进位
}
if (c[lenc + 1]) lenc++; // 判断最高位是否需进位
方法三:
方法二的改进,去掉c数组:
for (int i = 1; i <= lena; i++)
a[i] = a[i] + b[i]; // 直接加在a数组中
for (int i = 1; i <= lena; i++)
{
a[i + 1] = a[i + 1] + a[i] / 10; // 进位
a[i] = a[i] % 10; // 保留
}
if (a[lena + 1]) lena++; // 特判
最后的问题:——运算结果的输出:
for (i = lenc; i >= 1; i--)
printf("%d", c[i]); // 输出结果
printf("\n");
// ==============================
for (i = lenc; i >= 1; i--)
cout << c[i]; // 输出结果
cout << endl;
好的,关于高精度的每一个板块已经说明清楚了,下面我们来看一下完整的高精度运算:
(模板============================================================
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int a[506], b[506];
int lena, lenb;
int m;
string a1, b1;
int main(){
cin >> a1 >> b1; // 定义的字符串读入只可以用gets和cin,不能用scanf
lena = a1.length();
lenb = b1.length();
for (int i = 0; i <= lena - 1; i++){
a[lena - i - 1] = a1[i] - '0';
}
for(int i = 0; i <= lenb - 1; i++){
b[lenb - i - 1] = b1[i] - '0';
}
if(lena >= lenb){
for(int i = 0; i <= lena - 1; i++){
int ss = a[i];
a[i] = (b[i] + a[i] + m) % 10;
m = (ss + b[i] + m) / 10;
}
if(m) a[lena] = m;
else lena--;
for(int i = lena; i >= 0; i--) printf("%d", a[i]);
return 0;
}
else{
for(int i = 0; i <= lenb - 1; i++){
int ss = b[i];
b[i] = (b[i] + a[i] + m) % 10;
m = (ss + a[i] + m) / 10;
}
if(m) b[lenb] = m;
else lenb--;
for(int i = lenb; i >= 0; i--) printf("%d", b[i]);
return 0;
}
return 0;
}
此页面来源博客园!!
原页面:https://www.cnblogs.com/New-ljx/p/10480192.htmlfor 博客园
作者:dfydn
本文作者未含有权限
此文为AI-Deepseek转换markdown格式
这里空空如也




















有帮助,赞一个