各位小伙伴们大家好,我是小C哈哈哈,因为很忙,抽不出属于自己的时间,所以很久没有发博客了,但是好记性不如烂笔头。今天,我们就来谈一谈高精度减法。
首先谈论高精度减法之前,先说说为什么需要有高精度减法这样的算法存在,比如,现在你要用100位9减去8位9,很显然,在C++中,100位9这个数字无论是int类型还是long long 类型的变量都无法直接存储下来,而8位9的范围还在int类型规定的范围内,因此可以存储在int类型或者long long类型的变量之中。
以上两个整数做减法,其中第一个整数为大整数(范围太大,普通的int类型和long long类型变量无法存储),第二个整数为普通的整数(在int类型或long long类型的范围之内),像这样一个大整数减去一个普通整数的算法,我们可以称为高精度减法,实际上,高精度减法可以分为两种,第一种:大整数-普通整数,也称为高精度数-单精度数,第二种:大整数-大整数,也称为高精度数-高精度数。
现在我们假设高精度数大于等于单精度数,也就是说结果不会是负数。
思路:模拟数学上的竖式运算 ,如下图演示:将如下竖式的运算过程拆解
让高精度整数的第一位减去单精度整数
通过观察发现,高精度整数的第一位变成了负数,需要从下一位进行借位操作,于是我们让下一位减一,当前这位加上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、每个月至少打一次比赛。