当前位置: 首页 > news >正文

基础算法---【高精度算法】

前言

        高精度算法解决的就是数值特别大的数据之间的加减乘除的问题。基本思想就是先用字符串存入数据,然后再将这串数字逆序存放在数组里边。利用数组来模拟计算。

        为什么要逆序存在数组里边?原因就是我们小学时候的那种列竖式计算加减乘除的时候是先从个位开始计算的,而我们便利数组是从头开始便利的,所以逆序存放对于我们的计算更加的方便。

题目一:高精度加法

        https://www.luogu.com.cn/problem/P1601

解题思路

        当我们要将数据存放在数组里边的时候,要注意一个规律,请看下边的例子。

string s = "123"; 

int arr[] = {3,2,1};

上边字符串的长度为3,很容易就可以知道,字符串里边下标为0的位置的 ‘1’ 在数组里边是在下标为2的地方,而字符串里边下标为1的 ‘2’ 在数组里边是下标为1的位置。

仔细一想,0 + 2 == 2,1 + 1 == 2,因此我们就可以得到一个计算方式,字符串里边下标为i位置存放的数据对应存放在数组里边的下标为n - 1 - i(其中n为字符串的长度,n - 1就是字符串里边最大的下标)

        在将字符串里边读到的一个个字符数据存入数组的时候是需要减去'0'的,因为字符串里边的一个个数据是字符,而数组里边的一个个数据是数字,字符转化为数字就要减去'0',本质上就是ASCII码值相减的结果。

        当我们顺利的把数据存到数组里边的时候,我们就可以进行模拟加法运算了。

        在模拟加法运算的时候,我们需要三个数组a,b,c,其中a数组和b数组存放的是要进行加法运算的两个数,而c数组存的就是最终的结果。

        最后计算结束之后就直接打印数组c就可以得到我们的结果了。

代码实现

#include<iostream>
using namespace std;//题目描述里边的要读入的数据的位数为500,数组的大小可以拓展到1e6级别,高精度算法是支持的
const int N = 1e6 + 10;
int a[N], b[N], c[N];
int la, lb, lc;//表示的是数组的实际大小string x, y;//读入数字//高精度算法模板
void add(int c[], int a[], int b[])
{for (int i = 0; i < lc; i++){c[i] += a[i] + b[i];//用 += 是为了把c数组里边进位的结果也要一起加进去//处理进位c[i + 1] = c[i] / 10;//处理余数c[i] = c[i] % 10;}//考虑最高位发生进位的情况---默认情况下最高位是0,if判断条件是进不去的if (c[lc]){lc++;}
}int main()
{//1.读入数字cin >> x >> y;//2.将数字逆序存入数组//数组的实际大小根据读入的数字来定la = x.size();lb = y.size();lc = max(la, lb);//取两个数字的最大值(最高位发生进位再另外考虑)for (int i = 0; i < la; i++){a[la - 1 - i] = x[i] - '0';}for (int i = 0; i < lb; i++){b[lb - 1 - i] = y[i] - '0';}//进行模拟加法add(c, a, b);// c = a + b;//最后输出结果--逆序存放也要逆序打印for (int i = lc - 1; i >= 0; i--){cout << c[i];}return 0;
}

题目二:高精度减法

        https://www.luogu.com.cn/problem/P2142

解题思路

        基本思路还是字符串读入然后逆序存放在数组里边,再进行数学列竖式计算减法,对于两个数相减,是会存在减数大于被减数的情况的。如果直接列竖式相减就不符合逻辑,所以要先判断读入的两个数字的大小关系,从而需要保证被减数大于减数,然后就可以进行列竖式减法运算了。具体细节结合代码注释给出。

   对于比较被减数和减数的大小,由于是以字符串的形式读入的数字,因此如果直接比较就是字典序的比较,比如111和99比较,由于9的ASCII大于1的,所以导致直接比较出来111<99。这显然与我们想要的事实不符,所以我们可以采取先长度比较再字典序比较的方式,对于两个长度不一样长的字符串来说,长度长的对应的数字肯定是要大于长度短的,而如果两个字符串一样长的话,直接就以字典序的方式比较就可以了。

代码实现

#include<iostream>
using namespace std;const int N = 1e6 + 10;
int a[N], b[N], c[N];
int la, lb, lc;string x, y;//比较被减数和减数的大小
bool cmp(string& x, string& y)
{if (x.size() != y.size()){return x.size() < y.size();}else{return x < y;}
}//高精度减法模板
void sub(int c[],int a[],int b[])
{for (int i = 0; i < lc; i++){c[i] += a[i] - b[i];//用 += 是为了处理不够减向前借位的情况if (c[i] < 0)//借位{c[i + 1] -= 1;c[i] += 10;}}//处理边界情况while(lc > 1 && c[lc - 1] == 0){lc--;}
}int main()
{//1.读入cin >> x >> y;//2.判断x,y的大小if (cmp(x, y))//如果x < y,就返回true{swap(x, y);cout << "-";}//3.逆序存入数组la = x.size();lb = y.size();lc = max(la, lb);//边界情况最后处理for (int i = 0; i < la; i++){a[la - 1 - i] = x[i] - '0';}for (int i = 0; i < lb; i++){b[lb - 1 - i] = y[i] - '0';}//4.列竖式减法运算sub(c, a, b);//c = a - b//5.打印结果for (int i = lc - 1; i >= 0; i--){cout << c[i];}return 0;
}

        对于边界情况的处理,再详细说明一下。在进行减法的过程当中是会出现高位变成0的情况的,就像999 - 991,此时那些高位的0是不能算在lc里边的,所以lc--,但是有特殊情况就是如果是999 - 999,按照上边的做法,lc最后会变成0,可是正确的结果应该是0,所以还要加个lc > 1的判断。

题目三:高精度乘法

        https://www.luogu.com.cn/problem/P1303

解题思路

        第一步还是字符串读入,逆序存在数组里边。如果用常规的列竖式计算乘法,那么每一次相乘都要处理进位,有点太麻烦了,因此,我们在这里采用无进位相乘,请看下边的图示。

        最终结果所处在c数组(存放最终运算结果的数组)里边下标的位置通过找规律就可以发现,a数组下标为i的位置和b数组里边下标为j的位置对应相乘之后的结果在c数组里边是下标i + j的位置。注意上边图片里边模拟的乘法过程是还没有逆序存在数组里边的样子,因此我们找下标规律的时候是最右边下标从0开始。

代码实现

#include<iostream>
using namespace std;const int N = 1e6 + 10;
int a[N], b[N], c[N];
int la, lb, lc;string x, y;//高精度乘法模板
void mul(int c[], int a[], int b[])
{//无进位相乘---利用嵌套循环(取a数组的每一位和b数组的每一位相乘)for (int i = 0; i < la; i++){for (int j = 0; j < lb; j++){c[i + j] += a[i] * b[j];//用 += 是因为全部算出来了之后要累加}}//进位---跟高精度加法的时候的进位类似for (int i = 0; i < lc; i++){c[i + 1] += c[i] / 10;c[i] = c[i] % 10;}//处理最高位为0的情况---有可能是 0 * 999 == 0这种情况,跟高精度减法那里一样处理while(lc > 1 && c[lc - 1] == 0){lc--;}
}int main()
{//1.读入cin >> x >> y;//2.逆序存放在数组里边la = x.size();lb = y.size();lc = la + lb;//两数相乘的结果不会超过两个数的位数之和for (int i = 0; i < la; i++){a[la - 1 - i] = x[i] - '0';}for (int i = 0; i < lb; i++){b[lb - 1 - i] = y[i] - '0';}//3.高精度乘法mul(c, a, b);// c = a * b//4.打印结果for (int i = lc - 1; i >= 0; i--){cout << c[i];}return 0;
}

题目四:高精度除法

        注意这里提到的高精度除法其实是高精度除以低精度。高精度除以高精度的情况非常的少见,就不做介绍。

        https://www.luogu.com.cn/problem/P1480

解题思路

        我们只需要字符串读入,数组逆向存入那个高精度的数就可以了,剩下的一个数用内置类型来存储就可以了。接着就是模拟列竖式除法的过程。请看下边的示例图。

代码实现

#include<iostream>
using namespace std;const int N = 1e6 + 10;
int a[N], b, c[N];
int la, lc;//高精度除法(高精度 / 低精度)
void sub(int c[], int a[], int b)
{long long t = 0;//int类型是有可能存不下余数的//除法是从最高位开始除的,所以要倒着便利数组afor (int i = la - 1; i >= 0; i--){//计算被除数t = t * 10 + a[i];//商存在c数组里c[i] = t / b;//计算余数t = t % b;}//处理最高位为0的情况while (lc > 1 && c[lc - 1] == 0){lc--;}
}int main()
{//1.读入并且逆序存入数组string x;cin >> x >> b;la = x.size();lc = la;for (int i = 0; i < la; i++){a[la - 1 - i] = x[i] - '0';}//2.高精度除法运算sub(c, a, b);// c = a / b//3.打印结果for (int i = lc - 1; i >= 0; i--){cout << c[i];}return 0;
}

文章转载自:

http://je1ksgi8.Ldwxj.cn
http://5fx8yflt.Ldwxj.cn
http://XLqRWhQ3.Ldwxj.cn
http://Zt0MZpiF.Ldwxj.cn
http://UQ0sphVy.Ldwxj.cn
http://bCX24VUN.Ldwxj.cn
http://kULoqlp9.Ldwxj.cn
http://rYKIO0nG.Ldwxj.cn
http://WJZCbNQf.Ldwxj.cn
http://UlBPkyIX.Ldwxj.cn
http://8DmFHMTa.Ldwxj.cn
http://QpBQscpo.Ldwxj.cn
http://2xxNUJgg.Ldwxj.cn
http://VPA1RR0e.Ldwxj.cn
http://SF1Ea3oM.Ldwxj.cn
http://8op3XQXw.Ldwxj.cn
http://tVowbSpP.Ldwxj.cn
http://LPAuD5tB.Ldwxj.cn
http://lyYMxkXq.Ldwxj.cn
http://vhh70VLx.Ldwxj.cn
http://r3YpaIIk.Ldwxj.cn
http://wTh3XC8P.Ldwxj.cn
http://JukNy51p.Ldwxj.cn
http://ABAva6yp.Ldwxj.cn
http://c9zg7UaO.Ldwxj.cn
http://kRXkXhdh.Ldwxj.cn
http://J4MyHAsS.Ldwxj.cn
http://4tB1dZvz.Ldwxj.cn
http://ceEXVeYC.Ldwxj.cn
http://BCTeYDH2.Ldwxj.cn
http://www.dtcms.com/a/381425.html

相关文章:

  • React 18的createRoot与render全面对比
  • 在 React 中如何优化状态的使用?
  • 什么是半导体制造中的PVD涂层?
  • 半导体制造的光刻工艺该如何选择合适的光刻胶?
  • 用图论来解决问题
  • 机器视觉在半导体制造中有哪些检测应用
  • 从废料到碳减排:猎板 PCB 埋容埋阻的绿色制造革命,如何实现环保与性能双赢
  • CoCo:智谱推出的企业级超级助手Agent
  • 【高等数学】第十一章 曲线积分与曲面积分——第七节 斯托克斯公式 环流量与旋度
  • 嵌入式基础_STM32F103C8T6移植FreeRTOS(标准库函数)
  • 互联网大厂Java面试实录:从基础到微服务全栈技术答疑
  • DAY 28 类的定义和方法-2025.9.15
  • Linux信号小细节整理
  • Django全栈班v1.04 Python基础语法 20250913 下午
  • 第38次CCFCSP第三题--消息解码
  • 新零售第一阶段传统零售商的困境突破与二次增长路径:基于定制开发开源AI智能名片S2B2C商城小程序的实践探索
  • 金融科技:香港中小型企业(SME)市场规模、零售银行细分、家族办公室、私人银行、商业银行、渠道管理
  • 08_多层感知机
  • mysql基础——库与表的操作
  • Kafka系列之:Kafka broker does not support the ‘MetadataRequest_v0‘ Kafka protocol.
  • 06-Redis 基础配置与多数据库:从端口修改到数据隔离
  • Android真机-安装Reqable证书-抓SSL包
  • 贪心算法应用:决策树(ID3/C4.5)详解
  • 创建数据库索引时,要考虑一下这5个维度
  • 如何用 Rust 重写 SQLite 数据库?
  • Eureka挂了对整个服务的影响
  • 简单设计-小红书封面制作工具,小红书图文生成器
  • ​​Docker 容器化部署核心实战:从镜像仓库管理、容器多参数运行到 Nginx 服务配置与正反向代理原理解析​
  • 【目标检测】metrice_curve和loss_curve对比图可视化
  • 文件上传漏洞知识+21关文件上传漏洞教程