写在前面
本程序关键之处在于任意长度,所以变量不能是int或者一般的char数组,故此采用动态数组vector,vector容器会自动根据数据量的加减自动增加或减少长度。本程序加减法中的模拟手算的算法逻辑借鉴了STL容器之Vector大数运算,实现任意位数的两个整数的加减法运算一文,不过原博主代码有三个bug,在本程序中都得到了良好的解决。大家可以对比一下,互相学习。
原博的3个bug
1、两数相加时如果两个位数相同且最高位仍有进位时会有多进一个1,如999+999=11998 。
2、例如,9999-9998=0001,多余的零没有去除。
3、相同两数相减时,程序报错。
以上3个bug,在本程序中都得到了解决。
程序简介
根据设计模式的原则,本程序先声明一个计算基类Compute.h,计算基类里声明一个计算函数compute。加法类和减法类都继承这个计算基类。然后再在各自类内实现各自的算法。
Compute.h:
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Compute { //抽象计算类
public:
Compute() {}
~Compute() {}
virtual void compute(const string& strA, const string& strB) =0;
};
Add.h:
#pragma once
#include"Compute.h"
class Add :public Compute { //加法定义
public:
void compute(const string& strA, const string& strB) override;
};
Add.cpp:
#include"Add.h"
#include<vector>
#include<string>
//using namespace std;
void Add::compute(const string& strA, const string& strB)
{ //加法实现
vector<int> a;
vector<int> b;
vector<int> sum; //存放和的数组
int index = 0; //存放进位数,初始为零
for (int i = strA.size() - 1; i >= 0; i--) {//将字符串倒序插入数组
a.push_back(strA[i] - '0');//字符串转化为整型存放
}
for (int i = strB.size() - 1; i >= 0; i--) { //将字符串倒序插入数组
b.push_back(strB[i] - '0'); //字符串转化为整型存放
}
int i;
for (i = 0; i < (int)a.size() && i < (int)b.size(); i++) { //逐位相加
sum.push_back((a[i] + b[i] + index) % 10); //a+b+进位数对10取余,存放进和的数组
index = (a[i] + b[i] + index) / 10; //更新进位数:a+b+旧进位数除以10的商为新进位数
}
if (a.size() == b.size() && index!=0) //当两数长度相等且最高位仍有进位时(此时进位只能是1)
sum.push_back(1);
else {
if (i < (int)a.size()) { //当数组a长度较长时
for (; i < (int)a.size(); i++) {
sum.push_back((a[i] + index) % 10);
index = (a[i] + index) / 10;
}
}
if (i < (int)b.size()) { //当数组b长度较长时
for (; i < (int)b.size(); i++) {
sum.push_back((b[i] + index) % 10);
index = (b[i] + index) / 10;
}
}
if (index !=0) //仍有进位数时只能为1
sum.push_back(1);
}
cout << strA << " + " << strB << " = ";
for (vector<int>::iterator it = sum.end()-1;it >= sum.begin(); it--){
cout << *it;
if (it == sum.begin())
break;
}
cout << endl;
//vector清内存
vector<int>().swap(a);
vector<int>().swap(b);
vector<int>().swap(sum);
}
Sub.h:
#pragma once
#include"Compute.h"
#include<vector>
class Sub :public Compute { //减法定义
public:
void compute(const string& strA, const string& strB) override;
//string vectorTostring(vector<int>& res);
void removeZero(string& str);
};
Sub.cpp:
#include"Sub.h"
#include<vector>
#include <algorithm>
#include <sstream>
#include <iterator>
void Sub::compute(const string& strA, const string& strB) { //减法实现
vector<int> max; //存放被减数
vector<int> min; //存放减数
vector<int> res; //存放结果
if (strA == strB) { //两数相等时,相减结果为零
max.push_back(0);
min.push_back(0);
}
else if (strA > strB && strA.size() == strB.size()||strA.size() > strB.size()) { //字符串比较时同时控制字符串长度大小,strA > strB时,A为被减数、B减数
for (int i = strA.length() - 1; i >= 0; i--)
max.push_back(strA[i] - '0'); //逆序存放并转化为整型
for (int i = strB.length() - 1; i >= 0; i--)
min.push_back(strB[i] - '0');
}
else {
for (int i = strA.length() - 1; i >= 0; i--) //strA < strB时,A为减数、B被减数
min.push_back(strA[i] - '0');
for (int i = strB.length() - 1; i >= 0; i--)
max.push_back(strB[i] - '0');
}
int index = 0; //进位标志
int i;
//开始计算
for (i = 0; i < (int)min.size(); i++) { //数组位数相匹配时,遍历相减
if (max[i] < min[i]) { // max[i] < min[i]考虑借位
res.push_back((max[i] + 10 - min[i]) - index); //max[i]的值+借位10 - min[i] - 前一位的借位
index = 1; //向后一位借位
}
if (max[i] > min[i]) { //max[i]的值 > min[i]的值,不用考虑借位
res.push_back((max[i] - min[i] - index)); //max[i] - min[i] - 前一位的借位
index = 0; //不用借位
}
if (max[i] == min[i] && index == 0) { //max[i]的值 == min[i]的值,前面没有借位
res.push_back((max[i] - min[i])); //直接相减
index = 0;
}
if (max[i] == min[i] && index == 1) { //max[i]的值 == min[i]的值,前面有借位
res.push_back((max[i] + 10 - min[i] - index)); //相减,还要减去前面的借位
index = 1; //向后借位
}
}
if (max.size() == min.size()) { //两动态数组大小相等
cout << strA << " - " << strB << " = ";
if (strA < strB)
cout << "-";
//vector转化为string,利用字符串切除多余零
ostringstream stream;
copy(res.rbegin(), res.rend(), ostream_iterator<int>(stream, ""));
string s = stream.str();
s.resize(s.length());
removeZero(s); //去除多余前缀零
cout << s;
cout << endl;
}
else if (i < (int)max.size()) {
for (; i < (int)max.size(); i++) {
if (max[i] == 0 && index == 1) { //如果max[i] == 0,且前面有借位
res.push_back(max[i] + 10 - index); //max向后借位10-前面的借位
index = 1; //继续向后面借位
}
else if (max[i] != 0 && index == 1) { //如果max[i] != 0,且前面有借位
res.push_back(max[i] - index); //max[i]直接减去前面的借位
index = 0; //借位置0
}
else if (index == 0) { //前面没有借位
res.push_back(max[i]); //直接赋值
}
}
cout << strA << " - " << strB << " = "; //输出格式
if ( strA.size() < strB.size()) { //如果strA<strB,或strA长度<strB长度
cout << "-";
}
/* for (vector<int>::reverse_iterator it = res.rbegin(); it != res.rend();it++) {
cout << *it;
}*/
ostringstream stream;
copy(res.rbegin(), res.rend(), ostream_iterator<int>(stream, ""));
string s = stream.str();
s.resize(s.length());
removeZero(s); //去除多余前缀零
cout << s;
cout << endl;
}
//vector清内存
vector<int>().swap(max);
vector<int>().swap(min);
vector<int>().swap(res);
}
void Sub::removeZero(string& str) { //去除多余零的函数实现
string zero("0");
str.erase(0, str.find_first_not_of(zero));
// str.erase(str.find_last_not_of(zero) + 1);
}
main.cpp:
#include"Compute.h"
#include"Sub.h"
#include"Add.h"
#include<iostream>
int main() {
string strA, strB;
Compute* add = new Add();
Compute* sub = new Sub();
cout << "请输入两个任意长度非负整数,并用空格隔开:" << endl;
cin >> strA >> strB;
cout << "两数相加为:" << endl;
add->compute(strA, strB);
cout << "两数相减为:" << endl;
sub->compute(strA, strB);
if (add != NULL)
{
delete add;
add = nullptr;
}
if (sub != NULL)
{
delete sub;
sub = nullptr;
}
system("pause");
return 0;
}