如何用C语言实现超大整数(不大于10^1000)的加减运算

如何用C语言实现超大整数(不大于101000)的加减运算

由于C语言的整型数据储存机制,要想用C语言实现超大整数的加减运算可不像下面这么简单

int main()
{
	long long int a,b;
	scanf("%d %d",&a,&b);
	printf("%d\n",a+b);
}

如果使用上面的代码进行运算,数据稍大就可能发生溢出的现象,导致最终的结果不正确,并且有时难以察觉。那么该如何利用C语言实现超大整数的加减运算呢?

在我们人类眼中,字符串和数字是完全一样的,如果给定一串数字:12345,我们既可以认为它是一个数字(一万二千三百四十五),也可以认为它是一段数字序列(一二三四五)。基于此,我们便可以用字符串来储存超大整数,并将加减运算规则应用在字符串上。

加法规则:个位对齐,满十进一
减法规则:个位对齐,不够借位

首先我们需要获取用户给定的两个字符串记为num1和num2。由于正数前面是没有’+‘的,而负数前面是有’-'的,因此我们需要规范num1和num2的形式,确保num1[0]和num2[0]中保存的都是自身符号,这样可以让我们后面的实现过程更加顺利。

具体实现方法是:
	获取需要规范形式的字符串,记为num
	如果num[0]!='-'
	{
		num中所有元素后移一个单位
		num[0]='+'
	}

完成对字符串形式的规范后,我们需要实现个位对齐。考虑到两个字符串的长度可能不同,我选择的方法是将num1和num2的数字顺序颠倒(不改变符号的位置),如:

+123456 -> +654321
-134 -> -431

这样颠倒顺序后的num1和num2的个位都处在了索引为1的位置,我们只需在完成运算之后把最终结果再颠倒过来即可。

做好了这些准备工作后,就可以编写运算时的代码了。

首先,我们需要通过数字的符号确定运算的类型以及最终结果的符号。

符号相同:绝对值相加,符号取决于数字的符号
符号不同:较大绝对值-较小绝对值,符号取决于绝对值较大数的符号

至此,最终结果的符号我们已经确定下来了,我们还需要实现绝对值之间的加减运算。

这部分实现方法使用代码表示更为简洁,因此给出具体代码

各个变量的含义如下:
	ans:用于保存最终答案的字符串(a[0]保存了符号)
	num1:长度更长的字符串
	num2:长度更短的字符串
	len1:num1的长度
	len2:num2的长度
//绝对值相加
for (i=1; i<len2; i++)    //先遍历更短的字符串
{
	ans[i]+=num1[i]+num2[i]-'0';    
	//此时ans[i]中保存的就是字符形式的数字
		
	if (ans[i]>=10+'0')    //进位
	{
		ans[i]-=10;
		ans[i+1]++;
	} 
}
	
for (i=len2; i<len1; i++)    //再遍历更长的字符串
{
	ans[i]+=num1[i];
		
	if (ans[i]>=10+'0')    //进位 
	{
		ans[i]-=10;
		ans[i+1]++;
	}
}

len=strlen(ans);    //取此时ans的长度,以便确定'\0'的最终位置
ans[len]='\0';
	
for (i=len-1; ans[i]<'0'; i--)    
//考虑到进位时可能出现ans[i]+'0'='对应数字'的情况,对此进行检查
{
	ans[i]+='0';
} 
备注:
	1.声明了ans后务必进行初始化,将其中的元素全部置零:
			memset(ans,0,ans的长度)
	2.要分两次遍历字符串的原因:
		由于没有对num2[i](i>len2)进行初始化,num2[i](i>len2)可
		能是一些乱七八糟的值,如果此时进行运算,得到的ans[i]也会是一些
		乱七八糟的值。若希望仅用一次for循环,则应该在读取字符串前使用
			memset(num2,'0',num2的长度)
		进行初始化。

得到最终的ans后,根据其符号进行输出即可。
绝对值相减的方法与此大同小异,因此不再赘述。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值