全网最详细剖析讲解高精度减法

        各位小伙伴们大家好,我是小C哈哈哈,因为很忙,抽不出属于自己的时间,所以很久没有发博客了,但是好记性不如烂笔头。今天,我们就来谈一谈高精度减法。

        首先谈论高精度减法之前,先说说为什么需要有高精度减法这样的算法存在,比如,现在你要用100位9减去8位9,很显然,在C++中,100位9这个数字无论是int类型还是long long 类型的变量都无法直接存储下来,而8位9的范围还在int类型规定的范围内,因此可以存储在int类型或者long long类型的变量之中。

        以上两个整数做减法,其中第一个整数为大整数(范围太大,普通的int类型和long long类型变量无法存储),第二个整数为普通的整数(在int类型或long long类型的范围之内),像这样一个大整数减去一个普通整数的算法,我们可以称为高精度减法,实际上,高精度减法可以分为两种,第一种:大整数-普通整数,也称为高精度数-单精度数,第二种:大整数-大整数,也称为高精度数-高精度数。

        现在我们假设高精度数大于等于单精度数,也就是说结果不会是负数

思路:模拟数学上的竖式运算 ,如下图演示:将如下竖式的运算过程拆解

59234和9的减法结果

让高精度整数的第一位减去单精度整数

 通过观察发现,高精度整数的第一位变成了负数,需要从下一位进行借位操作,于是我们让下一位减一,当前这位加上10,这是两步操作。就会得到如下结果:

 

我们来看一下具体的操作步骤

(1)在高精度数组下标为0的位置减去单精度整数,当前指向这一位

(2)如果当前位上的数小于0,就让当前指向的下一位减去1,并让当前位加上10,

         直到当前位上的数不小于0

(3)向前移动一位,继续执行第二步操作


举个例子:计算12345-999的差

第一步:将12345这个数字存储到数组a中,即a[0]=5、a[1]=4、a[2]=3、a[3]=2、a[4]=1,有

第二步:将下标为0的数据元素也就是5减去999,得到-994

第三步:当前位为a[0],a[0]的值为-994,是小于0的,那么就让a[1]减去1为3,a[0]加上10,发现a[0]的值为-984,依然小于0,就让a[1]再减去1为2,a[0]加上10,发现a[0]的值为-974,继续让a[1]减去1为1,发现a[0]的值为-964,继续让a[1]减去1为0,发现a[0]的值为-954,发现a[0]的值依然是小于0的,这个时候以此类推,一直从十位上借位,直到十位等于-96,这个时候a[0]的值为6大于0,停止借位,此时十位a[1]等于-96

第四步:现在这个数为:1 2 3 -96 6

第五步:个位已经不小于0了,现在看十位,发现十位的数小于0,那么就向百位借位,这时百位为3,借一位变为2,此时十位a[1]从-96变成-86,依然小于0,继续借位,此时百位从2变为1,十位a[1]从-86变为-76,继续从百位借位,此时百位从1变为0,十位a[1]从-76变成-66,依然小于0,继续向百位借位,以此类推,一直从百位借位,直到百位等于-7,这时十位a[1]等于4,有:

 第六步:十位已经不小于0了,现在看百位,百位小于0,于是从千位上借位,千位为a[3]等于2,百位为a[2]等于-7,此时借位,那么千位a[3]变为1,此时百位a[2]变为3,那么结果为:

11346。继续查看下一位千位,不为0,就继续查看下一位万位,也不为0,得出答案,程序结束。有:

 

注意事项:进行减法操作之后,结果数据的长度有可能会变小,比如1234-1232等于2,所以需要判断结果数据的最高位是否为0,如果是0,需要让总长度减去1,特别需要注意的是,如果结果数据为0,那么要把这个0保留下来,比如1234-1234等于0,在判断的过程中,要保留0这个数据。

我们来看看高精度数据-单精度数据的核心代码:

a[0] -= x;    //x为单精读数据
for(int i = 0; i < len; i++)  //核心运算过程
{
    a[i+1]--;
    a[i]+=10;
}
//不允许有前导0,且如果结果是0,需要保留这个0,所以需要条件len > 1
while(len >1 && a[len-1] == 0)
{
    len--;
}

 不妨来看一下完整代码:

#include<bits/stdc++.h>
using namespace std;
string num;
int x, len;
int a[105];
int main() {
    cin >> num;
    cin >> x;
    len = num.size();
    //数据倒序存储
    for (int i = 0; i < len; i++) {
        a[i] = num[len - 1 - i] - '0';
    }
    //高精度个位减去单精度数
    a[0] -= x;
    //核心代码
    for(int i=0;i<len;i++)
    {
        while(a[i]<0){
            a[i+1]--;
            a[i]+=10;
        }
    }
    //去掉前导0
    while(len>1&&a[len-1]==0)
    {
        len--;
    }
    //输出数据
    for (int i = len - 1; i >= 0; i--) {
        cout << a[i];
    }
    return 0;
}

由于时间有限,在此就不讲解高精度减去高精度的算法过程了,这个过程相对来说还是比较简单的,下次如果有时间,再来讲解。

在这里分享一下学习算法最重要的三点:

1、做题     

2、数学(可以先掌握中小学数学)       

3、每个月至少打一次比赛。 

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值