【大数运算】大数的加减乘除

大数加法

对于加法来说,思路和阶乘的一样,就是每一位每一位地依次来看。

首先把两个数都装进数组里,同时比较长度,(len1比len2长则之后只是依次加到len1长度),如果某位相加的结果>=10,则令m=1,否则m=0,让下一位记得加了之后再+m

代码via静之吾心

#include<stdio.h>
#include<string.h>
int x[100]={0},y[100]={0},z[105]={0};//将数组元素全部初始化为0 
int main()
{
	char a[100],b[100];//通过字符串对大数进行输入并储存 
	int len1,len2,len;
	while(scanf("%s %s",a,b))
	{
		int i,j=0,k=0;
		len1=strlen(a);
		len2=strlen(b);
		for(i=len1-1;i>=0;i--)//将两个字符串中的字符转化为数字,并倒序储存到数组中,即字符串为123456,则数组为654321 
		{
			x[j]=a[i]-'0';
			j++;
		}
		for(i=len2-1;i>=0;i--)
		{
			y[k]=b[i]-'0';
			k++;
		}
		if(len1>len2)
            len=len1;
        else
            len=len2;
		i=0;//从最低位(个位)开始进行计算
		int m=0;
		for(i=0;i<len;i++)
		{
			z[i]=(x[i]+y[i]+m)%10;//将所得数的个位存到数组z[i]中去 
			if((x[i]+y[i]+m)>=10)
				m=1;
			else
				m=0;
		}
		if((x[i-1]+y[i-1]+m)>=10)//判断最高位还需不需要进位
			z[i]=1;
		else
			i=i-1;
		for(;i>=0;i--)//到序输出数组 
			printf("%d",z[i]);
		printf("\n");
	}
	return 0; 
}

大数减法

要联系大数加法,在编程设计上注意的点:

①不管加法和减法,都是要依次看到两个数中的最长长度的位数上去。比如6012-12的结果还是要看到第四位去

加法要进位,减法要借位。加法的进位有可能最高位还要进不知道多少位出去,所以要考虑到这一点。但减法的借位,如果默认a-b的a>b,则不存在最高位还需要去借位,这样可以简便很多运算,只需要在调用函数前去判断a>b即可,如果a<b则先输出一个负号再交换a,b参数顺序即可。

③加法不需要考虑结果的前导0,而减法要考虑比如6012-6010=0002这种情况,输出的时候不要输出前导0.

AC代码:

#include<iostream> 
#include<bits/stdc++.h>
using namespace std;

int x,y; //要求x-y
int a[500],b[500];

void sub(int a[],int b[],int len) //这里默认a是大于b的,具体在主函数里进行case判断了 
{
	int jie = 0;
	//从低位到高位依次对应相减,如果减不过就借位
	for(int i=1;i<=len;i++)
	{
		int temp;
		if(a[i]-jie<b[i])  
		{
			jie = 1; //需要借位,给下一位的jie赋为1 
			temp = a[i]+10-b[i];
		}
		else
		{
			temp = a[i] - jie - b[i]; //注意,如果我用这种方法,则要先-jie,再jie=0 
			jie = 0; 
		}
		a[i] = temp;
	} 
	//注意这里不用像加法一样还要去考虑最高位有进位,因为已经默认a>b了,所以不存在最高位还需要借位的情况
	 
	//输出的时候要注意:有可能有前导0!!!!(而加法无需考虑 
	for(int i=len;i>=1;i--)
	{
		if(a[i]==0)
			len--;
		else
			break;
	} 
	for(int i=len;i>=1;i--)
		cout<<a[i];
	cout<<endl;
}



int main()
{
	char sa[500],sb[500]; //建立字符数组,这样就可以方便直接调用函数来求长度
	cin>>sa>>sb; //当作字符串输入 
	int len1 = strlen(sa);
	int len2 = strlen(sb);
	//char数组转换成int数组,方便运算
	for(int i=len1;i>=1;i--) //从下标为1开始存储,方便看。注意从低位->高位的顺序存 
		a[i] = sa[len1-i] - '0';
	for(int i=len2;i>=1;i--)
		b[i] = sb[len2-i] - '0';
	
	if(len1>len2) //被减数更大
		sub(a,b,len1);
	else if(len1<len2) //减数更大,结果为负数
	{
		cout<<"-";
		sub(b,a,len2);
	}
	else if(len1==len2) //两个数相同长度,还是应该比较大小,不然不好确定符号
	{
		int a_bigger = 0;
		for(int i=len1;i>=1;i--)
		{
			if(a[i]>b[i])
			{
				a_bigger = 1;
				break;
			}
		}
		if(a_bigger==1)//说明被减数更大	
			sub(a,b,len1);
		else //说明减数更大
		{
			cout<<"-";
			sub(b,a,len2);
		} 
	} 
		 
	return 0;
}

大数乘法

和阶乘的做法大体相同,但是注意,阶乘由于每个位可以乘上很大的数,所以num要一直保留且传下去,而对于乘法对应位的相乘,最多9*9=81,所以只需要把多出来的第二位的值加到下一位,本位保留个位的值即可。

这里要get到一个点:在第5位的数值为a,其实际含义是a*10000。所以,第i位和第j位的数相乘,实质是i位数*j位数=i*j位数,因此,其结果应该放在i*j位上。

for(i=0;i<len1;i++)//将因数各个位上的数字与另一个各个位上的数字相乘 
		{
			for(j=0;j<len2;j++)
				z[i+j]=z[i+j]+x[i]*y[j];//先乘起来,后面统一进行进位。这里要理解!!!
		}
		for(i=0;i<MAX*2;i++)//进行进位  MAX是二者位数最长长度
		{
			if(z[i]>=10)  //若>=10 
			{
				z[i+1]=z[i+1]+z[i]/10;  //将十位上数字进位 
				z[i]=z[i]%10;  //将个位上的数字留下
			}
		}
		for(i=MAX*2;i>0;i--)  //删除0的前缀 因为用的位数是MAX*2,不一定真能达到这么长
		{
			if(z[i]==0)
				continue;
			else
				break;
		}
		for(;i>=0;i--)  //倒序输出 
			printf("%d",z[i]);

--------------------- 
作者:静之吾心 
来源:CSDN 
原文:https://blog.csdn.net/lisp1995/article/details/52316466 
版权声明:本文为博主原创文章,转载请附上博文链接!

大数除法

代码逻辑并没有想象中那么难。实际上的“求商”就是被除数减去除数的倍数,倍数以10递减,直到最后剩下的数小于除数,则为余数

以28536 除以23 为例来看一下:开始商为0。

先减去23 的1000 倍(先补0直至除数位数==被除数位数),就是23000,发现够减1 次,余下5536,于是商的值就增加1000;

然后用5536减去2300,发现够减2 次,余下936,于是商的值增加200,即1200;

再用936 减去230,够减4 次,余下16,于是商值增加40,即1240。

最后,发现余下的数比23小,即为余数,即28536 / 23 得1240余16。

猜你喜欢

转载自blog.csdn.net/m0_38033475/article/details/91952967