高精度算法——高精度减法

介绍:

高精度减法也同加法一样,也是用于位数太大的运算,给你一个十几位的数你可能会做直接开个long long 的数据类型就解决了,但是给你一个100位的呢,1000位的呢,开long long 也不够了,所以就要用高精度了,也就是高精度算法就是处理位数很大数据。
如果你对高精度加法也不是很熟悉你可以看这个(高精度算法——高精度加法

减法过程:

  • 首先我们先来看下小学的知识减法
123
24
99
  • 我们来简单的分析下好吧,就当我们都还是小学生呢(🤭)
  • 开始做这个减法之前我们还要知道什么是减数,什么是被减数。
  • 这个就是字面意思,被减数,有个被字对吧,就是那个会减少的数就是被减数,这里就是123对吧,理解了被减数,这个减数当然也就出来了,24就是减数了。
  • 好了,被减数和减数知道了,咱就可以开始做减法吧。
  • 也是和加法一样,先从个位开始减的,先看3,3减4不够减是吧,所以就要从前面借一位,这里借的1,是在十位上借的,实际上是借了10,这个没毛病吧,也就是现在个位上是3 加上的10 等于13 了,所以再用13 - 4 这下就知道了吧,就是9了
  • 现在十位上的数被借走一位,所以要减一变成了1,然后再用1减2,又发现不够减了,当然也是和上面一样,这里就不再那么啰嗦了,最后就是答案了 99,没毛病吧。
  • 这个大概看了下小学知识,下面就开始模拟这个过程。

模拟过程:

  • 同样也是用数组去模拟,你可以认为数组是 ‘万能’ 的,如果学了数据结构就知道了,什么链表,栈,队列,树等都是可以用数组去模拟的
  • 先创建三个数组 a[1000], b[1000], c[1000].两个用来存放被减数和减数,一个用来存放最后答案
  • 同样是用字符串形式去输入,如果你要用整型的就会出错,几百位的数都爆掉了,所以只能用字符串的形式去输入。
  • 我们是从个位数去减的,然而输入是从头去输入的,所以要经过反转
for (int i = 0; i < str1.size(); i ++)
	a[i] = str1[str1.size()-1-i] - '0'; // 反转123
for (int i = 0; i < str2.size(); i ++)
	b[i] = str2[str2.size()-1-i] - '0'; // 反转24
  • 反转的时候我们顺便转化为整型,因为肯定不能用字符串去做减法是吧。
  • 现在已经做了个初步算法,下面就可以去模拟减法了,其实这里也是要和高精度加法一样先求长度,不然就不好控制下面的循环
int len = max(str1.size(), str2.size());
for (int i = 0; i < len; i ++) {
	if (a[i] < b[i]) {
		a[i+1] -= 1;
		a[i] += 10;
	}c[i] = a[i] - b[i];
}
  • 从这里看出来,当前面的数不够也就是a[i] 不够被减,所以就要先前借一位,
    所以就有a[i+1] -= 1,相当于借了10,所以当前的数就要加10,就有a[i] += 10
  • 最后就是相减了c[i] = a[i] - b[i]
  • 当然这里也是和高精度加法一样也是要去前导零的,我们先来分析下前导零出现的位置,不管怎么减最后的答案的位数最大也就是被减数或者是减数的位数,或者更小,不可能超过最大的位数,所以就不需要和高精度加法一样先加1再去前导零
while (c[len-1] == 0 && len > 1)
	len --;
  • 为什么这里是用while循环呢,是这样的,首先下标是从零开始的所以就要先减1,对吧,主要是有可能有相同的数相减,这样就会全部变成零了,但是我们只要输出一个零,所以就必须要用循环,但是不能一直减下去是吧,所以还要大于1.
  • 最后就是输出是吧
for (int i = 0; i < len; i ++)
    cout << c[len-1-i];
  • 到这里你以为就完了吗,那你就大错特错了,你再想想看还有没有落了什么点。
  • 你看到这里我们都是用我给的那个样例来说是吧,123-24,是不是大的数减小的数,得出来的整数是吧,那我给你一个小的数减大的数呢,是不是就忘记考虑这种情况了呢,
  • 好的,那我们现在再这个基础上再来讨论下这种情况
  • 先说下会出现的情况
  • 有可能相同的位数相减但是时被减数小,所以减出来是负数比如100-999
  • 还有可能是不同的位数相减,前面就是小的 比如10 -999
  • 也就这两种可能了,好的,下面用代码写下
if ((atoi(str1.c_str()) < atoi(str2.c_str()) && str1.size() == str2.size()) || str1.size() < str2.size()){
    swap(str1, str2);
    flag = 1;
}
  • 这里其实是捡了巧的,我是用了函数去转化的,
  • atoi()加上str.c_str(),是为了把字符串转化为整数,前面就是位数相等但是前面的数小了,后面就是 原本前面的数就小
  • 然后就交换下的位置,一直然大的减小的,这样就可以一直得到整数,不用考虑负号的问题,但是,负号不能不写是吧,所以就得用flag == 1标记下,等于1 就说什么此时是负数。
  • 现在才是完整的高精度减法,到这里应该是理解了吧。
  • 现在你们可以做下这题练练手(高精度减法

顺便附上这题的代码吧:

#include<iostream>
#include<string>
using namespace std;
const int N = 10090;
int a[N], b[N], c[N];
int flag = 0;
int main()
{
    string str1;
    string str2;
    cin >> str1;
    cin >> str2;
    if ((atoi(str1.c_str()) < atoi(str2.c_str()) && str1.size() == str2.size()) || str1.size() < str2.size()){
        swap(str1, str2);
        flag = 1;
    }
    for (int i = 0; i < str1.size(); i ++)
        a[str1.size()-1-i] = str1[i] - '0';
    for (int i = 0; i < str2.size(); i ++)
        b[str2.size()-i-1] = str2[i] - '0';
    int ans = max(str1.size(), str2.size());
    for (int i = 0; i < ans; i ++){
        if (a[i] < b[i]){
            a[i+1] -= 1; // 向前位借一位
            a[i] += 10;  // 后一位就得加10
        }c[i] = a[i] - b[i];  // 之后就是正常减法了
    }
    while (c[ans-1] == 0 && ans > 1)
        ans -= 1;
    if (flag == 1)
        cout << "-";
    for (int i = 0; i < ans; i ++)
        cout << c[ans-1-i];
    return 0;
}
  • 12
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值