• 高精度加法


      在昨天,我在有道小图灵官网进行了两场考试,其中一场考试的最后一道题就时一道简单运算,就是要运用到高精度算法,而那时候我还没有学习高精度,于是就在今天,我在B站什么找了视频来听,把高精度乘法、除法、加法、减法都给学会了。

      今天,我就来写一个关于高精度算法的总结,首先,我们要知道C++为什么要用到高精度算法,首先我们知道,C++中最大的整数类型就是long long ,最大范围是10的18次方,但是如果超过了10的18次方怎么办,存都存不下,更别谈运算了,这种数被称为高精度数和大整数!

      先给大家说一下高精度的名词:

    低精:
    直接可以使用 C++ 中有的数据类型进行定义。比如 15,678,808,877 这个数,我们可以用 long long 来定义。

    高精加高精:
    高精度数加上高精度数。

    高精乘高精:
    高精度数乘上高精度数。

    高精乘低精:
    高精度数乘上低精度数。

    高精除高精:
    高精度数除以高精度数。

    高精除低精:
    高精度数除以低精度数。

      接下来,我们就可以正式开始高精度运算了,我们先从高精度加法算起,我们在小学二三年级的时候,做一些加法题都需要用到竖式计算,而这种竖式计算是无论多大的数都可以算出来的,所以我们可以借助模拟竖式计算的方法来进行高精度加法运算。

    思路:

    1. 定义存储数组。
    2. 读入数据到数组中。注意是倒序存放,也就是个位放在数组下标为 0 的地方。
    3. 从个位开始模拟竖式加法的过程,完成整个加法。
    4. 删除前导 0 。所谓前导零,就是出现类似这样数据 01234,这个 0 实际是不需要的。
    5. 输出加法的结果。倒序输出加法的结果数组 C,因为我们的个位是存储在下标为 0 的地方。

    我们先来看一看存储结构:

    1. const int N=1e5+10;
    2. char s1[N]={};//存储字符串
    3. char s2[N]={};//存储字符串
    4. int a[N]={};//存储加数A
    5. int b[N]={};//存储加数B
    6. int c[N]={};//存储和C

    读入数据:

       我们先输入s1,s2两个字符串,然后再求出两个字符串的长度l1和l2,之后将s1[i]赋值给a[i],将s2[i]赋值给b[i],用int类型数组更容易计算一些!

    1. scanf("%s %s",s1,s2);
    2. int l1=strlen(s1);
    3. int l2=strlen(s2);
    4. for(int i=0;i
    5. a[i]=s1[l1-i-1]-'0';
    6. for(int i=0;i
    7. b[i]=s2[l2-i-1]-'0';

    模拟竖式加法:

        首先,我们要将a[i]和b[i]加起来,存到c[i]里面,在将他们的进位存在jw里面,每次运算加上去,哪怕是0,之后再将c[i]对10来取模,是求进位过后这个位是什么数字!

    1. //模拟竖式加法
    2. int jw=0;//进位
    3. int l=max(l1,l2)+1;//注意因为最高位可能出现进位
    4. for(int i=0;i
    5. {
    6. c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
    7. jw=c[i]/10;//本次加法是否存在进位
    8. c[i]%=10;//只能保存0~9的数据
    9. }

    有两个细节需要注意:

    1. 进位如何保存;
    2. 最高位进位如何解决。 

    删除多余的0:

      由于我们是倒着来的前面有很多多余的0,我们用for循环倒着删除,如果遇到0了,就将c[i]的长度减1,直到碰见第一个不是0的最高位,就break;结束删除!

    1. //删除前导零
    2. for (int i=l-1;i>=0;i--)
    3. {
    4. //因为我们是从下标0开始,所以最高位是保存在l-1
    5. if(0==c[i]&&l>1)
    6. {
    7. //注意要有 l>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
    8. len--;
    9. }
    10. else
    11. {
    12. //第一个不是零的最高位,结束删除
    13. break;
    14. }
    15. }

    输出计算结果: 

      最后就是将计算结果输出就行了,用for循环一个一个来打印!

    1. //逆序打印输出
    2. for (int i=l-1;i>=0;i--)
    3. {
    4. printf("%d",c[i]);
    5. }
    6. printf("\n");

    高精度加法的完整代码:

    1. #include
    2. using namespace std;
    3. const int N=200+4;
    4. char s1[N]={};//存储字符串
    5. char s2[N]={};//存储字符串
    6. int a[N]={};//存储加数A
    7. int b[N]={};//存储加数B
    8. int c[N]={};//存储和B
    9. int main()
    10. {
    11. scanf("%s %s",s1,s2);//读入字符串A
    12. //将字符串写入到数组A中
    13. int l1=strlen(s1);
    14. for(int i=0;i
    15. {
    16. //倒序写入
    17. a[i]=s1[len1-i-1]-'0';
    18. }
    19. //将字符串写入到数组A中
    20. int l2=strlen(s2);
    21. for(int i=0;i
    22. {
    23. //倒序写入
    24. b[i]=s2[len2-i-1]-'0';
    25. }
    26. //模拟竖式加法
    27. int jw=0;//进位
    28. int l=max(l1,l2)+1;//注意因为最高位可能出现进位
    29. for(int i=0;i
    30. {
    31. c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
    32. jw=c[i]/10;//本次加法是否存在进位
    33. c[i]%=10;//只能保存 0 ~ 9 的数据
    34. }
    35. //删除前导零
    36. for(int i=l-1;i>=0;i--) {
    37. //因为我们是从索引 0 开始,所以最高位是保存在 len-1
    38. if(0==c[i]&&len>1)
    39. {
    40. //注意要有 len>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
    41. l--;
    42. }
    43. else
    44. {
    45. //第一个不是零的最高位,结束删除
    46. break;
    47. }
    48. }
    49. //逆序打印输出
    50. for (int i=l-1; i>=0; i--)
    51. {
    52. printf("%d", c[i]);
    53. }
    54. printf("\n");
    55. return 0;
    56. }

       今天就先讲到这里,下一期我会给大家说一说高精度减法!

  • 相关阅读:
    docker镜像原理
    Qt扫盲-QBrush理论使用总结
    plt画图柱状图解决横坐标字体显示的问题竖体显示
    C# ref 学习1
    TCP链接异常: SYN_RECV
    微电子领域常见概念(九)势垒层
    无法将“node.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
    机器学习之机器如何学习
    【框架】跨端开发框架介绍(Windows/MacOS/Linux/Andriod/iOS/H5/小程序)
    任务执行大数据量与高并发方案
  • 原文地址:https://blog.csdn.net/wo_ai_luo_/article/details/126069776