高精度计算(一)大数加减法

概述

​ 当计算的数值非常大或是对于计算的精度要求非常搞事,用已知的数据类型无法精确地表示数值。可以采用数组来模拟大数运算的过程。

高精度加法

两个大数进行相加计算时,要解决三个问题

  1. 如何存储
  2. 如何计算
  3. 如何输出答案

先解决第一个问题,数据地存储,由于数据过于庞大,已知的数据类型无法精确地表示数值,会发生数据溢出问题。此时可考虑将数据拆分,将大数分割成若干个0~9数字组成的整体。这样的结构能让我们联想到数组。但是,若是整数数组,在输入时较难将数字存储在各个元素空间内,此时可考虑使用字符串形式进行输入,在存储后再进行转换。

const int maxn=1e10+5;
char s1[maxn]={0},s2[maxn]={0};
cin>>s1>>s2;

输入完成后,再去考虑计算问题。首先,字符类型直接相加的结果并不正确,需要将其转化为整数数字。可利用ASCII码差值来进行处理。且在进行计算时,模拟竖式加法计算过程,需要从低位开始向高位相加计算且注意过程中的进位。在相加时,加数和被加数位数可能不同,需要低位对齐。实现低位对齐可在转换时进行倒序存放。

// 转换过程
int num[maxn]={0};
int len=strlen(s);

for(int i=0;i<len;i++)
{
    num[i]=s[len-1-i]-'0';
}

倒序转换好之后,在模拟竖式计算进行处理。注意过程中的进位。

int ans[maxn]={0};
for(int i=0;i<maxLen;i++)
{
	ans[i]+=num1[i]+num2[i];
	ans[i+1]=ans[i]/10;//进位
	ans[i]%=10;//保留余数
}

计算完成之后可以进行输出,这时候需要注意答案是倒着存放的,需要倒序进行输出并去除前导0;

int flag=0;
for(int i=maxLen+1;i>=0;i--)
{
	if(ans[i]!=0||i==0) flag=1;
    if(falg) cout<<ans[i];
}

高精度减法

高精度减法和高精度加法过程类似,字符串输入后模拟竖式进行计算。

前面数据输入和倒置存放的过程相同就不再重复。再计算过程中需要注意的问题就是可能相减会出现负数,两数相减需要考虑绝对值大小问题。

计算a-b,若a>=b,ans=a-b;若a<b,ans=-(b-a);故需要判断大小,可根据长度来判断大小,长度相同则使用字符串比较函数,从字符串内容上进行判断。

int len1=strlen(s1);
int len2=strlen(s2);

if((len1>len2) || (len2==len1&&strcmp(s1,s2)>=0 )
{
    //ans=a-b;
    for(int i=0;i<len1;i++)
    {
        if(num1[i]<num2[i]){
            num1[i]+=10;
            num1[i+1]--;
        }
        ans[i]=num1[i]-num2[i];
    }
}else
{
    //ans=-(b-a);
    for(int i=0;i<len2;i++)
    {
        if(num2[i]<num1[i]){
            num2[i]+=10;
            num2[i+1]--;
        }
        ans[i]=num2[i]-num1[i];
    }
    cout<<"-";
}

算完后,再和前面一样进行倒序输出答案,注意删除前导0即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值