C++实现大数运算 加法部分。

6 篇文章 0 订阅

由于编程语言提供的基本数值数据类型表示的数值范围有限,不能满足较大规模的高精度数值计算,因此需要利用其他方法实现高精度数值的计算,于是产生了大数运算。大数运算主要有加、减、乘三种方法。

所以我就打算做一个大数运算的项目。

其中每个数字,是动态分配的字符串的形式进行存储和计算的。

下面是每个数的类的组成

class Bigint 
{
public:
	Bigint() {}
	Bigint(const char *);//用字符串创建大数。
	Bigint(int);        // 用传入的参数n,创建长度为n的大数,默认为0;
	Bigint(Bigint &); 
	int getlength();
	~Bigint();
	char *num;
	int length;
	friend ostream & operator<<(ostream &, Bigint &);
};
运算的核心代码

class Operation
{
public:
	Operation(const char *str1, const char *str2);
	~Operation();
	virtual Bigint& GetResult();
	Bigint num1;
	Bigint num2;
	Bigint result;
	char ch;
};


class OperationAdd : public Operation
{
public:	
	OperationAdd(const char *str1, const char *str2);
	virtual Bigint& GetResult();
};
这里 运用了简单的工厂模式,用C++的多态和虚函数,实现了代码的低耦合,方便以后进行修改和增添。

Operation类的实现

Operation::Operation(const char *str1, const char *str2) :num1(str1), num2(str2){}
Operation::~Operation(){}
Bigint& Operation::GetResult()
{
	return Bigint("0");
}

这里显式调用了Bigint类的构造函数,而且由于放在{}中,C++编译器会自动认为这是重载()的运算,所以只能用冒号语法,来进行初始化。

OperationAdd类的实现

下面的子类的构造函数是直接调用父类的构造函数,同理,也只能用冒号语法。

OperationAdd::OperationAdd(const char *str1, const char *str2) :Operation(str1, str2) {}
Bigint& OperationAdd::GetResult()
{
	int carrynum = 0;
	result.num = new char[(result.length = num1.length > num2.length ? num1.length + 1 : num2.length + 1)+1];
	int length = result.length - 1;
	int temp = 0;
	for (int i = num1.length -1, j = num2.length -1; length >= 0;)
	{
		if(i >= 0 && j >= 0)
		{ 
			temp = num1.num[i--] + num2.num[j--] + carrynum - 2 * '0';
			result.num[length--] = temp % 10 + '0';
			carrynum = temp / 10;
		}
		else if (i >= 0)
		{
			temp = num1.num[i--] + carrynum - '0';
			result.num[length--] = temp % 10 + '0';
			carrynum = temp / 10;
		}
		else if (j >= 0)
		{
			temp = num2.num[j--] + carrynum - '0';
			result.num[length--] = temp % 10 + '0';
			carrynum = temp / 10;
		}
		else if (carrynum != 0)
		{
			result.num[length--] = carrynum + '0';
		}
		else
		{
			for (int k = 0; k < result.length - 1; k++)
			{
				result.num[k] = result.num[k + 1];
			}
			result.length--;
			length--;
		}
	}
	result.num[result.length] = '\0';
	return result;
}
这个加法的具体实现:

  首先我们的决定结果result的长度,我们可以这样想,两个数相加,有两种可能:1.保持最大数的位数;2.在最大数的位数基础上进了一位;

在这里我取了最大可能的位数。

   加法过程模仿手工过程,个位+个位,满十进位。如果两个都有数的话

			temp = num1.num[i--] + num2.num[j--] + carrynum - 2 * '0';
			result.num[length--] = temp % 10 + '0';
			carrynum = temp / 10;
由于是两个字符的相加,所以需要减去两个‘0’,转到0~9的相加,carrynum是进位数,默认第一次为0,两个数相加,比如5 + 6  

它们的和和10取余就是留在个位的数,它们的和和10相除就是留在十位的数。

假设有一个数num2相加的时候没有数了的时候,实现应该是

			temp = num1.num[i--] + carrynum - '0';
			result.num[length--] = temp % 10 + '0';
			carrynum = temp / 10;
还是应该取一下进位和本数的和,因为有可能9999999 + 1呢!

在两个数都没有位数的时候,而length还没有完的时候


		else if (carrynum != 0)
		{
			result.num[length--] = carrynum + '0';
		}
		else
		{
			for (int k = 0; k < result.length - 1; k++)
			{
				result.num[k] = result.num[k + 1];
			}
			result.length--;
			length--;
		}

这个就是看又没有进位,如果有进位,就把第一位即result.num[0] =carrynum + '0';

如果没有进位的话,就集体向前移一位,防止有01513这种情况出现。

这样就实现了大数的运算,部分实现,我没有给出,这个项目还不完善,比如还有其他运算没有实现,比如没有宽展到小数部分,

等我将全部实现后,咱们githup见吧,有什么改进意见可以留言还有对乘法有什么好的实现方式 也可以帮帮博主,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值