知识铺垫(高精度算法):
在C/C++中,我们经常会碰到限定数据范围的情况,
C++规定:
int占32位,即4个字节,即int的范围是[-231,231-1],为10^9数量级
long long占64位,即8个字节,即long long的范围是[-263,263-1],为10……18数量级
如果超过该数量级,则需引入高精度算法。
1.高精度加法
A+B Problem(高精)
题目描述
高精度加法,相当于 a+b problem,不用考虑负数。
输入格式
分两行输入。a,b<=10^500。
输出格式
输出只有一行,代表 $a+b$ 的值。
样例 #1
样例输入 #1
1
1
样例输出 #1
2
样例 #2
样例输入 #2
1001
9099
样例输出 #2
10100
提示
$20%$ 的测试数据,0<=a,b<=10^9;
$40%$ 的测试数据,0<=a,b<=10^18。
#include<iostream>
#include<cstring>
char s1[505],s2[505];
int a[505],b[505],c[505];
using namespace std;
int main()
{
int la,lb,lc;// la: s1的长度, lb: s2的长度, lc: 结果的长度
// 输入两个大数的字符串表示
cin>>s1;
cin>>s2;
// 计算输入字符串的长度
la=strlen(s1);
lb=strlen(s2);
// 将第一个字符串的数字转换为整数数组(反向存储)
for(int i=0; i<la; i++)
{
a[la-i]=s1[i]-'0'; // s1[i] 转换为数字并存储在 a 中
}
// 将第二个字符串的数字转换为整数数组(反向存储)
for(int i=0; i<lb; i++)
{
b[lb-i]=s2[i]-'0';// s2[i] 转换为数字并存储在 b 中
}
// 设置结果的最大可能长度
lc=max(la,lb)+1;// 加一是为了处理可能的进位
// 进行大数相加
for(int i=1; i<=lc; i++)
{
c[i]+=a[i]+b[i];// 对应位相加
c[i+1]=c[i]/10;// 计算进位
c[i]=c[i]%10; // 当前位数值
}
// 去掉结果前面的零
if(c[lc]==0&&lc>0)lc--;
// 输出最终结果
for(int i=lc; i>0; i--)
cout<<c[i];// 从高位到低位输出
return 0;
}
2.高精度减法
高精度减法
题目描述
高精度减法。
输入格式
两个整数 $a,b$(第二个可能比第一个大)。
输出格式
结果(是负数要输出负号)。
样例 #1
样例输入 #1
2
1
样例输出 #1
1
提示
- $20%$ 数据 $a,b$ 在 long long 范围内;
- $100%$ 数据 $0<a,b<10^10086$。
#include <iostream>
#include <cstring>
using namespace std;
// 定义字符串和数组的大小
char s1[110090], s2[10090], s3[10090];
int a[10090], b[10090], c[10090];
int flag = 0; // 用于标记结果符号
// 比较两个字符串的函数
bool compare(char s1[], char s2[]) {
// 如果两个字符串完全相同,返回 true
if (strcmp(s1, s2) == 0) return true;
int u = strlen(s1), v = strlen(s2); // 获取两个字符串的长度
// 如果 s1 长度大于 s2,返回 true(s1 更大)
if (u > v) return true;
// 如果 s1 长度小于 s2,返回 false(s2 更大)
else if (u < v) return false;
// 如果长度相等,逐字符比较
else if (u == v) {
for (int i = 0; i < u; i++) {
// 返回第一个不同字符的比较结果
if (s1[i] != s2[i]) return s1[i] > s2[i];
}
}
}
int main() {
int la, lb, lc; // 字符串长度变量
// 输入两个大数
cin >> s1;
cin >> s2;
// 如果 s1 不大于 s2,则交换它们
if (!compare(s1, s2)) {
flag = 1; // 设置标记,表示结果是负数
strcpy(s3, s1); // 临时保存 s1
strcpy(s1, s2); // 将 s2 赋值给 s1
strcpy(s2, s3); // 将原来的 s1 赋值给 s2
}
la = strlen(s1); // 获取 s1 的长度
lb = strlen(s2); // 获取 s2 的长度
// 将 s1 转换为逆序的数字数组 a
for (int i = 0; i < la; i++) {
a[la - i] = s1[i] - '0'; // 字符转数字,并存储在 a 中
}
// 将 s2 转换为逆序的数字数组 b
for (int i = 0; i < lb; i++) {
b[lb - i] = s2[i] - '0'; // 字符转数字,并存储在 b 中
}
lc = max(la, lb); // 结果的最大位数
// 大数减法运算
for (int i = 1; i <= lc; i++) {
if (a[i] < b[i]) { // 如果 a 当前位小于 b 当前位
a[i + 1]--; // 向高位借一
a[i] += 10; // 当前位加上 10
}
c[i] = a[i] - b[i]; // 计算当前位的结果
}
// 去掉前导零
while (c[lc] == 0 && lc > 1) lc--;
// 如果 flag 为 1,说明结果是负数,输出负号
if (flag == 1) cout << "-";
// 输出结果,从最高位到最低位
for (int i = lc; i > 0; i--) {
cout << c[i];
}
return 0;
}
浙公网安备 33010602011771号