在昨天,我在有道小图灵官网进行了两场考试,其中一场考试的最后一道题就时一道简单运算,就是要运用到高精度算法,而那时候我还没有学习高精度,于是就在今天,我在B站什么找了视频来听,把高精度乘法、除法、加法、减法都给学会了。
今天,我就来写一个关于高精度算法的总结,首先,我们要知道C++为什么要用到高精度算法,首先我们知道,C++中最大的整数类型就是long long ,最大范围是10的18次方,但是如果超过了10的18次方怎么办,存都存不下,更别谈运算了,这种数被称为高精度数和大整数!
接下来,我们就可以正式开始高精度运算了,我们先从高精度加法算起,我们在小学二三年级的时候,做一些加法题都需要用到竖式计算,而这种竖式计算是无论多大的数都可以算出来的,所以我们可以借助模拟竖式计算的方法来进行高精度加法运算。
- const int N=1e5+10;
- char s1[N]={};//存储字符串
- char s2[N]={};//存储字符串
- int a[N]={};//存储加数A
- int b[N]={};//存储加数B
- int c[N]={};//存储和C
我们先输入s1,s2两个字符串,然后再求出两个字符串的长度l1和l2,之后将s1[i]赋值给a[i],将s2[i]赋值给b[i],用int类型数组更容易计算一些!
- scanf("%s %s",s1,s2);
- int l1=strlen(s1);
- int l2=strlen(s2);
- for(int i=0;i
- a[i]=s1[l1-i-1]-'0';
- for(int i=0;i
- b[i]=s2[l2-i-1]-'0';
模拟竖式加法:
首先,我们要将a[i]和b[i]加起来,存到c[i]里面,在将他们的进位存在jw里面,每次运算加上去,哪怕是0,之后再将c[i]对10来取模,是求进位过后这个位是什么数字!
- //模拟竖式加法
- int jw=0;//进位
- int l=max(l1,l2)+1;//注意因为最高位可能出现进位
- for(int i=0;i
- {
- c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
- jw=c[i]/10;//本次加法是否存在进位
- c[i]%=10;//只能保存0~9的数据
- }
有两个细节需要注意:
- 进位如何保存;
- 最高位进位如何解决。
删除多余的0:
由于我们是倒着来的前面有很多多余的0,我们用for循环倒着删除,如果遇到0了,就将c[i]的长度减1,直到碰见第一个不是0的最高位,就break;结束删除!
- //删除前导零
- for (int i=l-1;i>=0;i--)
- {
- //因为我们是从下标0开始,所以最高位是保存在l-1
- if(0==c[i]&&l>1)
- {
- //注意要有 l>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
- len--;
- }
- else
- {
- //第一个不是零的最高位,结束删除
- break;
- }
- }
输出计算结果:
最后就是将计算结果输出就行了,用for循环一个一个来打印!
- //逆序打印输出
- for (int i=l-1;i>=0;i--)
- {
- printf("%d",c[i]);
- }
- printf("\n");
高精度加法的完整代码:
- #include
- using namespace std;
- const int N=200+4;
- char s1[N]={};//存储字符串
- char s2[N]={};//存储字符串
- int a[N]={};//存储加数A
- int b[N]={};//存储加数B
- int c[N]={};//存储和B
- int main()
- {
- scanf("%s %s",s1,s2);//读入字符串A
- //将字符串写入到数组A中
- int l1=strlen(s1);
- for(int i=0;i
- {
- //倒序写入
- a[i]=s1[len1-i-1]-'0';
- }
- //将字符串写入到数组A中
- int l2=strlen(s2);
- for(int i=0;i
- {
- //倒序写入
- b[i]=s2[len2-i-1]-'0';
- }
- //模拟竖式加法
- int jw=0;//进位
- int l=max(l1,l2)+1;//注意因为最高位可能出现进位
- for(int i=0;i
- {
- c[i]=a[i]+b[i]+jw;//当前加数A位数据+加数B位位数据+上一位的进位
- jw=c[i]/10;//本次加法是否存在进位
- c[i]%=10;//只能保存 0 ~ 9 的数据
- }
- //删除前导零
- for(int i=l-1;i>=0;i--) {
- //因为我们是从索引 0 开始,所以最高位是保存在 len-1
- if(0==c[i]&&len>1)
- {
- //注意要有 len>1 这个条件。考虑特殊情况,加法结果为 00,我们实际要输出 0。
- l--;
- }
- else
- {
- //第一个不是零的最高位,结束删除
- break;
- }
- }
-
- //逆序打印输出
- for (int i=l-1; i>=0; i--)
- {
- printf("%d", c[i]);
- }
- printf("\n");
-
- return 0;
- }
今天就先讲到这里,下一期我会给大家说一说高精度减法!
-
相关阅读:
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