首页 > 编程知识 正文

c语言超大数据运算,大数相加c语言编程

时间:2023-05-06 04:49:34 阅读:276635 作者:1912

由于整型数的位数有限,因此整型数不能满足大整数(超长整数)的运算要求 。大整数计算是利用字符串来表示大整数,即用字符串的一位字符表示大整数的一位数值,然后根据四则运算规则实现大整数的四则运算。

大数的结构

typedef struct bigint{ char *num; //指向长整数数组(序号0中保存着最高位) char sign; //符号(1表示正数,-1表示负数) int digit; //保存该数的位数(实际位数) }BIGINT, *pBIGINT;

加法运算

执行加法之前,先判断两数是同号相加还是异号相加,同号则执行加法运算,异号则执行减法运算。在加法运算中,首先将被操作的两个数对齐,然后从低位向高位逐渐相加,在对应位置相加时,要考虑是否有地位相加的进位。

实现代码:
首先将被加数中的内容复制到结果数组中,然后从低位逐渐加到结果中去,最后判断加数各位加完之后是否还有进位,如果有则要累加到高位中去。BigintTirm()用于整理大数,去掉前多余的0,并调整其位数

void BigIntAdd(pBIGINT num1,pBIGINT num2,pBIGINT result){ int i,carry; carry=0; //清除进位 result->sign =num1->sign; //保存符号 //将被加数复制到结果数组中 for(i=0;i<num1->digit;i++) result->num[i]=num1->num[i]; //num2中的数小,可能位数也少些 for(i=0;i<num2->digit;i++) { //将对应位的数和进位数相加 result->num[i]=result->num[i]+num2->num[i]+carry; carry=result->num[i]/10; //计算进位数据 result->num[i]=result->num[i]%10; //保留一位 } if(carry) //若最后还有进位 result->num[i]=result->num[i]+carry; BigIntTrim(result); //整理结果 }

减法运算
减法运算可以看做异号加法,结果的最大位数和较大的减数位数相同,可以把被减数缺少的位数用零补全然后相减,也可以只减到被减数的位数,然后将减数的高位直接写到结果的数组中。


实现代码:

void BigIntSub1(pBIGINT num1,pBIGINT num2,pBIGINT result) { int i,borrow; result->sign =num1->sign; //结果符号 borrow=0; //将被减数的内容复制到结果中 for(i=0;i<num1->digit;i++) result->num[i]=num1->num[i]; for(i=0;i<=num2->digit;i++) { //num1减去num2,并减去低位的借位 result->num[i]=result->num[i]-num2->num[i]-borrow; if(result ->num[i]<0) //若为负数 { result->num[i]=10+result->num[i]; //向高位借位 borrow=1; //设置借位数 }else borrow=0; } if(borrow==1) result->num[i]=result->num[i]-borrow; i=num1->digit; while(i>0) { if(result->num[i]==0) i--; else break; } result->digit=i+1; //保存结果位数 BigIntTrim(result); //整理结果 }

乘法运算
对于乘法运算,以乘法的每一位去乘以被乘数。例如,首先以乘数的个位去乘被乘数,将结果通过进位处理后保存到结果位中。接着用乘数的十位去乘以被乘数,将每位计算结果累加到最终结果中。


实现代码:
两个数相乘最大的位数是两个乘数的位数之和,在乘法中我们需要每执行一次乘法就要对数组进行进位的处理。

void BigIntMul(pBIGINT num1,pBIGINT num2,pBIGINT result){ char carry,temp; int i,j,pos; //结果数组和中间数清0 for(i=0;i<num1->digit+num2->digit;i++) result->num[i]=0; //用乘数的每一位乘以被乘数 for(i=0;i<num2->digit;i++) { carry=0; //清除进位 //被乘数的每一位 for(j=0;j<num1->digit;j++) { //相乘并加上进位 temp=num2->num[i] * num1->num[j]+carry; //计算进位carry carry =temp/10; //计算当前位的值 temp=temp%10; pos=i+j; //计算结果累加到临时数组中 result->num[pos]+=temp; carry=carry+result->num[pos]/10; //计算进位 result->num[pos]=result->num[pos]%10; } if(carry>0) { result->num[i+j]=carry; //加上最高位进位 result->digit=i+j+1; //保存结果位数 }else result->digit=i+j; //保存结果位数 } result->sign=num1->sign * num2->sign; //结果的符号 }

除法运算
对于大数除法运算,首先取被除数的最高两位作为部分被除数,去除以除数,根据该部分被除数与除数的结果——商,得到一位数的商。
除法对数据有限制不能分母为零,分母为零没有意义;不能用小数除以大数


实现代码:
返回的结果是保存商的数组的指针,不包含余数。

void BigIntDiv(pBIGINT num1,pBIGINT num2,pBIGINT result,pBIGINT residue){ BIGINT residol; int i,j,k,m; //k保存试商结果,m保存商的位数 char t; result->sign = num1->sign * num2->sign; //商的符号 //分配余数的内存空间 residue->num =(char *)malloc(sizeof(char) * num2->digit); for(i=0;i<residue->digit;i++) //将余数全部清0 residue->num[i]=0; m=0; for(i=num1->digit-1;i>=0;i--) { //重新设置余数的位数比除数多一位 residue->digit=num2->digit+1; for(j=num2->digit-1;j>0;j--) //移余数 residue->num[j]=residue->num[j-1]; //复制被除数中的一位到余数的最低位中 residue->num[0]=num1->num[i]; BigIntTrim(residue); //整理余数 k=0; //试商 //比较余数与除数的大小 while(BigIntEqual(residue,num2)>=0) { BigIntSub1(residue,num2,residue); //用余数减去除数,差值保存在余数中 k++; //试商加1 } result->num[m++]=k; //保存商 } result->digit=m; //保存商的位数 for(i=0;i<m/2;i++) //反转商的值 { t=result->num[i]; result->num[i]=result->num[m-1-i]; result->num[m-1-i]=t; } BigIntTrim(result); //整理商 BigIntTrim(residue); //整理余数 }

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。