用vector实现任意长度的非负整数加减运算(基于C++/STL)

该程序使用C++ STL库中的Vector实现任意位数整数的加减法,修复了原代码中的三个错误:1.两数相加时高位多进位;2.减法结果多余零未去除;3.相同数相减报错。通过动态数组处理不同长度的数字,确保正确计算和输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

本程序关键之处在于任意长度,所以变量不能是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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值