高精度加法
高精度运算在C++中通常是通过字符串或数组来实现的,因为标准库中的整型变量通常不能存储超过32位或64位的数值。以下是一个高精度加法的示例代码:
#include<bits/stdc++.h>
using namespace std;
//高精度加法
string highAccAdd(const string &a, const string &b) {
string result;
int carry = 0;
// 反转字符串,便于从个位开始逐位相加
string A = a, B = b;
reverse(A.begin(), A.end());
reverse(B.begin(), B.end());
for (size_t i = 0; i < A.length() || i < B.length(); ++i) {
int x = i < A.length() ? A[i] - '0' : 0;
int y = i < B.length() ? B[i] - '0' : 0;
int sum = x + y + carry;
result += (sum % 10) + '0'; // 更新结果字符串
carry = sum / 10; // 更新进位
}
if (carry > 0) {
result += '1'; // 如果最后还有进位,添加到结果字符串末尾
}
reverse(result.begin(), result.end()); // 最终结果需要反转回来
return result;
}
int main() {
string num1 = "123456789";
string num2 = "987654321";
string sum = highAccAdd(num1, num2);
cout << sum << endl;
return 0;
}
#include<iostream>
#include<vector>//使用vector容器前需包含此文件
using namespace std;
//vector(vector &v) ; //加上'&' 为引用数组v,则不需要再拷贝一份,提高效率
vector<int> add(vector<int> &A,vector<int> &B)
{
vector<int> C;
//进位标识符t
int t=0;
for(int i=0;i<B.size()||i<A.size();i++)
{
/*
两个if语句都是在判断A或B容器对应的数位上是否还有数据
如果没有则对应数位上是+0,即不加。
*/
if(i<A.size()) t+=A[i];
if(i<B.size()) t+=B[i];
//要的是t个位上的数
C.push_back(t%10);
//舍弃掉个位数,让t十位数上的值参与到下一位数的运算中
t/=10;
}
//如果t不等于零,则在最高位补1。对应数位相加(两位数的加法),进位是0或1;
if(t) C.push_back(1);
return C;
}
int main()
{
string a,b;
/*
vector<int> 把vector理解成一个数组,但与数组不同的是:
vector是动态储存,保存在堆中。
动态扩展是找到比原来更大的内存空间,将原数据拷贝到新空间,释放 原 空间
*/
vector<int> A,B;
cin >> a >> b;
/*
push_back()是将括号里的元素插入至尾部
A.push_back(a[i]-'0')//意味着将a[i]-'0'这个数插到A容器的最后面
但由于A容器中无元素,所以插到了第一位上
*/
//逆序读入,方便于运算
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
vector<int> C=add(A,B);
//逆序输出
for(int i=C.size()-1;i>=0;i--) cout << C[i];
return 0;
}
这段代码实现了高精度加法,其中highAccAdd函数接受两个字符串参数,代表要相加的高精度数值,并返回它们的和。在实现中,我们通过字符串反转对字符进行逐位处理,避免了直接将字符转换为数值的需要,这样可以有效处理任意长度的数值。最后,结果字符串需要再次反转并返回。
高精度减法
在C++中实现高精度减法稍微复杂一些,因为需要处理借位和负数的情况。下面是一个高精度减法的示例代码:
#include <bits/stdc++.h>
using namespace std;
//高精度减法
string highAccSubtract(const string &a, const string &b) {
string result;
int borrow = 0;
// 假设 a >= b
// 反转字符串,便于从个位开始逐位相减
string A = a, B = b;
if (a < b) {
string tmp = A;
A = b;
B = tmp;
borrow = 1; // 标记结果为负数
}
reverse(A.begin(), A.end());
reverse(B.begin(), B.end());
for (size_t i = 0; i < A.length(); ++i) {
int x = A[i] - '0';
int y = (i < B.length()) ? B[i] - '0' : 0;
int diff = x - y - borrow;
if (diff < 0) {
diff += 10; // 借位
borrow = 1;
} else {
borrow = 0;
}
result += diff + '0'; // 更新结果字符串
}
// 移除结果字符串前导的0
while (result.length() > 1 && result.back() == '0') {
result.pop_back();
}
if (borrow) {
// 如果最后还有借位,说明原始的a < b,返回负数结果
result = "-" + result;
}
reverse(result.begin(), result.end()); // 最终结果需要反转回来
return result;
}
int main() {
string num1 = "123456789";
string num2 = "98765432";
string diff = highAccSubtract(num1, num2);
cout << diff << endl;
// 负数示例
num1 = "123456789";
num2 = "1234567891";
diff = highAccSubtract(num1, num2);
cout << diff << endl;
return 0;
}
#include<bits/stdc++.h>
#include<vector>
using namespace std;
/*
判断a与b的大小
*/
bool check(vector<int> &a,vector<int> &b)
{
//长度不相等,直接返回a.size()>b.size(),如果a.size()>b.size()则为真,否则为假
if(a.size()!=b.size()) return a.size()>b.size();
//长度不相等
for(int i=a.size();i>=0;i--)//从最高位开始判断
//如果最高位不相等
if(a[i]!=b[i])
//同上
return a[i]>b[i];
//两种情况都判断过还是没结果,说明a=b,直接返回真
return true;
}
//减,对应数位相减
vector<int> sub(vector<int> &a,vector<int> &b)
{
//经过check函数之后,a的大小一定大于b
vector<int> C;//定义容器C
int t=0;
for(int i=0;i<a.size();i++)
{
t+=a[i];
if(i<b.size()) t-=b[i];
//倘若相减为负数,那么需进行借位操作。为正也不影响
C.push_back((t+10)%10);
//重新对t赋值
if(t<0) t=-1;
else t=0;
}
//这一步是去前导0,如果用数组来做,那就是压缩数组C的体积
//注意即使全为0,那么就要保存最后一位
while(C.size()>1&&C.back()==0) C.pop_back();//去顶
return C;
}
int main()
{
string a,b;
cin >> a >> b;
vector<int> A,B,C;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
if(check(A,B))
{
C=sub(A,B);
for(int i=C.size()-1;i>=0;i--) cout << C[i];
return 0;
}
else
{
C=sub(B,A);
//如果A的长度小于B,提前输出一个符号
cout << "-";
for(int i=C.size()-1;i>=0;i--) cout << C[i];
return 0;
}
}
在这段代码中,highAccSubtract函数首先判断a是否小于b,如果是,则交换它们并标记结果为负数。然后,它逐位相减,处理借位,并构建结果字符串。最后,如果最初a小于b,则在结果前添加负号。同样地,我们需要移除结果字符串前导的0,并在返回结果之前将字符串反转回来。
请注意,这段代码没有处理字符串转换为数值时的溢出问题。在实际应用中,你可能需要添加额外的逻辑来处理非常大的数值,这些数值的每一位相减都可能导致溢出。此外,这个实现假定输入的字符串都是有效的正整数表示,并且没有前导零。在实际应用中,你可能需要添加额外的输入验证来确保这些假设成立。