高精度原理介绍及代码实现

目录

高精度

引入

使用场景

实现原理

高精度加法

数据存储

加法实现

总代码

高精度减法

与加法的不同点:

总代码

高精度乘法

总代码

高精度除法

总结

总注意点

减法注意点

高精度

引入

所谓高精度并不是很高级难懂的东西,只是对传统的加减法模拟实现

使用场景

高精度算法(High Accuracy Algorithm)的出现是为了处理超大数据的数学计算问题。在一般的科学计算中,我们可能会遇到需要计算小数点后几百位甚至更多的数字,或者处理几千亿、几百亿这样的大数字。这些数字超出了标准数据类型(如整型、实型)能够表示的范围,因此无法直接在计算机中正常存储和计算

实现原理

在高精度算法中,我们并不会把数据用int,long long,double这种数据结构来存储,而是用数组来存储,接下来我就讲讲其原理

高精度加法

数据存储

先从简单的加减运算说起,我们拿 23 + 25这个例子来举例,根据小学所学知识,我们知道当我们计算时应该列出这样子的式子:

如果我们要进行加法,那么我们将从右加到左,一一进位

而我们的算法将这里的27处理为:A[2] = {7,2};25处理为:B[2] = {5,2};

他们的和仍然是一个数组:C[2] = {2, 5};

你可能好奇,为什么是倒着存?🧐🤨

俺在前面也说过:从右加到左,因此,当我倒着存时,最低位(27的最低位为7)就在A[0],而当A[0] + B[0]要进位时,进位的1就被加到了C[1],综上所述,倒着存是为了方便进位(i进的位直接存在了i + 1的位置)(也就是7 + 5进的位存在了C[1])

倒着存应该怎么写呢?🤨🤨🤨

很简单,我们要注意读入数据时不能把存数据的变量设置为int,long long了,而是要设置为string

//a + b = c
​
int A[505];//第一个加数的数组
int B[505];//第二个加数的数组
int C[506];//和的数组
int len_c;
int main()
{string a, b;//注意用字符串读入cin >> a >> b;
​int len_a = a.size(), len_b = b.size();//len_a表示a有几个数字(若a = 1,则len_a = 1,若a = 10,则len_a = 2)int len_c = max(len_a, len_b);//a 和 b的和c最初设置为a 和 b的最大值,因为要确保每位都参与加法,就得让位数多的每位都加上//逆序存for (int i = 0; i < len_a; i++)A[len_a - 1 - i] = a[i] - '0';//注意 - ‘0’,因为是字符读入,且逆序存for (int i = 0; i < len_b; i++)B[len_b - 1 - i] = b[i] - '0';//注意 - ‘0’Add();return 0;
}

接下来就是重要的加法实现了

加法实现

先看代码

void Add()
{for (int i = 0; i < len_c; i++){C[i] += A[i] + B[i];C[i + 1] += C[i] / 10;C[i] %= 10;}
​if (C[len_c])len_c++;
}
  • for循环:for循环是从0开始的,这是因为我们存储的时候0位放的就是加数的最低位(27的7)

  • A[i] + B[i]:模仿传统加法(我们例子中就是:7 + 5)

  • C[i + 1] += C[i] / 10;:模仿进位(我们例子中就是:(7 + 5) / 10 = 1,因此在C[1]上进位了1)

  • C[i] %= 10; : 本位进位完后就要变为只有个位(我们例子中就是:(7 + 5) /%10 = 2,因此在C[0]上只有2)

  • if (C[len_c]) len_c++;:如果结果中最高位下一位不为0,说明len_c的长度要++

    如同:

    9 7 + 3,在len_c = max(len_a, len_b);后,len_c的长度为2,但是当计算完97 + 3 = 100后:之前的最高位(第二位)的下一位(第三位)不为0(100的1),长度变为3,因此要更新len_c

没想到吧,到这里就把高精度讲完啦,你看到这里很棒了哦,给你一个赞 d=====( ̄▽ ̄*)b

总代码

//a + b = c
​
int A[505];//第一个加数的数组
int B[505];//第二个加数的数组
int C[506];//和的数组
int len_c;
​
void Add()
{for (int i = 0; i < len_c; i++){C[i] += A[i] + B[i];C[i + 1] += C[i] / 10;C[i] %= 10;}
​if (C[len_c])len_c++;
}
​
int main()
{string a, b;//注意用字符串读入cin >> a >> b;
​int len_a = a.size(), len_b = b.size();len_c = max(len_a, len_b);for (int i = 0; i < len_a; i++)A[len_a - 1 - i] = a[i] - '0';//注意 - ‘0’,且逆序存for (int i = 0; i < len_b; i++)B[len_b - 1 - i] = b[i] - '0';//注意 - ‘0’
​Add();
​for (int i = 0; i < len_c; i++)cout << C[len_c - 1 - i];//注意逆序输出,因为存的时候是逆序的return 0;
}

高精度减法

这也是类似的,高精度通用的就是:

  • 数据用字符串读入,用数组存数

  • 要倒着存储数据

  • 注意进位

  • 注意逆序输出

与加法的不同点:

敲重点了哦~ψ(`∇´)ψ

  • 要看两个数据谁更大,要把大的作为a,小的作为b

  • 若起初a < b,用标记标记该答案为负数,以便最后得出答案时输出符号

总代码

//与加法相似
//加了调转字符串的操作
int main()
{string str1, str2;cin >> str1;cin >> str2;
​//两个数字最大为10^10086,因此数组设为10088就可(咱图个吉利)int a[10088] = { 0 }, b[10088] = { 0 }, c[10088] = { 0 };int flag = 0;//标记是否进行了调转字符串
​//与加法不同的是减法要调转字符串,把位数多的放前面,方便计算//至于负号,可以先标记,最后再进行处理
​if (str2.size() > str1.size()/*如果起初的b > a,---->要调转a, b, 把原先的a 变为 b*/||(str2.size() == str1.size()&&str1<str2)){/*!!!!!!!!!!!!!!!!!!!!注意或者后面的情况,若只有或者前面部分的,若是3-4这种情况,则无法算出正确答案*///str1<str2:前者的数字小于后面的数,虽然这是字符串,但仍然可以这样比较flag = 1;//标记进行了调换:方便最后输出 - 号swap(str1, str2);//调转的函数,具体的大家可以去自行了解}
​for (int i = 0; i < str1.size(); i++){a[i] = str1[str1.size() - 1 - i] - '0';//减'0'别忘了}
​for (int i = 0; i < str2.size(); i++){b[i] = str2[str2.size() - 1 - i] - '0';}
​//因为一开始就进行了调换最长的数放在str1,所以这里不需要取str1和str2中最长的赋值给lenfor (int i = 0; i < str1.size(); i++){c[i] = a[i] - b[i];if (c[i] < 0){a[i + 1]--;c[i] = a[i] + 10 - b[i];//记得给a[i]加10,就是模拟实际的计算}}
​//因为一开始就进行了调换最长的数放在str1,所以这里不需要取str1和str2中最长的赋值给len,叶不用进行len++//直接判断是否要进行len--int len = str1.size();
​/*是while,不是if*/
​while(c[len - 1] == 0 && len > 1)len--;
​
​if (flag == 1)//输出负号printf("-");for (int i = 0; i < len; i++)//仍然是倒着输出{printf("%d", c[len - 1 - i]);}printf("\n");
​return 0;
}

高精度乘法

总代码

int c[5000];
int len_a, len_b, len_c;
void mul(int a[], int b[])
{for (int i = 0; i < len_a; i++){for (int j = 0; j < len_b; j++){c[i + j] += a[i] * b[j];//注意是 +=c[i + j + 1] += c[i + j] / 10;c[i + j] = c[i + j] % 10;}}
​while (len_c > 1 && c[len_c - 1] == 0)//注意要len_c > 1,如果乘积为0,就会一直减下去,最后什么都不输出,这是错误的//注意是c[len_c - 1] == 0len_c--;
}
​
int main()
{string a, b;cin >> a >> b;len_a = a.size(), len_b = b.size();len_c = len_a + len_b;int aarr[2005], barr[2005];
​//倒着存for (int i = 0; i < len_a; i++)aarr[i] = a[len_a - 1 - i] - '0';//记得 - '0'for (int i = 0; i < len_b; i++)barr[i] = b[len_b - 1 - i] - '0';mul(aarr, barr);
​//cout << len_c << endl;//倒着输出for (int i = 0; i < len_c; i++)cout << c[len_c - 1 - i];return 0;
}

高精度除法

脑子不好的小菜鸟正在学习中::>_<::

总结

总注意点

综上所述,所谓的高精度就是模仿传统的运算法则,注意总点如下:

  • 不用数据类型存储数据,因为计算机存不下那么大的数字

  • 数组存储,且逆序存储

  • 注意进位,还有前置0

    (如:100 - 90 = 010,这个最高位的0是不输出的,要用如下句子处理掉:

    while (len_c > 1 && c[len_c - 1] == 0)//注意要len_c > 1,如果答案为0,就会一直减下去,最后什么都不输出,这是错误的//注意是c[len_c - 1] == 0len_c--;

减法注意点

  • 要看两个数据谁更大,要把大的作为a,小的作为b

  • 若起初a < b,要用标记标记该答案为负数,以便最后得出答案时输出符号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/11172.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】多态(上)超详细

封装&#xff0c;继承&#xff0c;多态不只是C的三大特性&#xff0c;而是面向对象编程的三大特性。 什么是多态&#xff1a; 不同的对象做同一件事情&#xff0c;结果会出现多种形态。 1.满足多态的几个条件 1.父子类完成虚函数重写&#xff08;需要满足三同&#xff1a;函…

历史文件清理

应用系统中可能会被要求保存一些文件记录&#xff0c;比如配置文件修改的备份&#xff0c;日志文件&#xff0c;备份文件。不过历史文件不一定是要求永久保留的&#xff0c;一般会有合规要求和业务要求&#xff0c;超过一定期限的可以删除&#xff0c;以释放空间&#xff0c;提…

VP Codeforces Round 944 (Div 4)

感受&#xff1a; A~G 其实都不难&#xff0c;都可以试着补起来。 H看到矩阵就放弃了。 A题&#xff1a; 思路&#xff1a; 打开编译器 代码&#xff1a; #include <iostream> #include <vector> #include <algorithm> #define int long long using na…

ETL(抽取、转换、加载)

ETL&#xff08;抽取、转换、加载&#xff09; 目录 ETL&#xff08;抽取、转换、加载&#xff09; 1.抽取&#xff08;Extract&#xff09; 2.转换&#xff08;Transform&#xff09; 3. 加载&#xff08;Load&#xff09; 4.ETL 工具和技术 5.总结 ETL&#xff08;抽取、转…

编写Spring项目:流程与思路指南

编写Spring项目&#xff1a;流程与思路指南 本文以初级工程师的视角&#xff0c;介绍了Spring项目开发的全流程&#xff0c;从项目初始化到部署上线&#xff0c;每一步骤都配有必要的指导和建议。希望这份指南能够帮助初级工程师快速上手Spring项目开发&#xff0c;并在未来的…

【机器学习】数据分析特征

参考来源&#xff1a;https://www.bilibili.com/video/BV1nt411r7tj 1.数据质量分析 缺失值 异常值&#xff1a;箱线图 一致值&#xff08;多数据源不一致&#xff09; 2.图像可视化 占比&#xff1a;饼图、气泡图&#xff08;2-5维&#xff09; 波动图&#xff1a;折线…

Windows Docker 使用 httpd 部署静态 Web 站点

一、简介 httpd 是 Apache超文本传输协议&#xff08;HTTP&#xff09;服务器的主程序&#xff0c;是一个独立运行的后台进程&#xff0c;专门负责处理 HTTP 请求。它通过建立子进程或线程的池来高效管理请求&#xff0c;确保服务器能够迅速响应客户端的需求。httpd 因其高效率…

MySQL查询篇-聚合函数-窗口函数

文章目录 distinct 关键字聚合函数常见的聚合函数group by和having 分组过滤 窗口函数with as窗口聚合函数排名窗口函数值窗口函数 distinct 关键字 distinct 去重数据&#xff0c;ps:null值也会查出来 select distinct column from table;聚合函数 常见的聚合函数 select …

[AutoSar]BSW_Diagnostic_002 DCM模块介绍

目录 关键词平台说明背景一、DCM所处架构位置二、DCM 与其他模块的交互三、DCM 的功能四、DCM的内部子模块4.1 Diagnostic Session Layer (DSL)4.1 DSL 与其他模块的交互 4.2 Diagnostic Service Dispatcher (DSD)4.3 Diagnostic Service Processing (DSP)4.4 小结 关键词 嵌入…

linux程序分析命令(二)

linux程序分析命令(二) **ldd&#xff1a;**用于打印共享库依赖。这个命令会显示出一个可执行文件所依赖的所有共享库&#xff08;动态链接库&#xff09;&#xff0c;这对于解决运行时库依赖问题非常有用。**nm&#xff1a;**用于列出对象文件的符号表。这个命令可以显示出定…

Python元类:深入解析及其在框架开发中的应用

Python元类&#xff1a;深入解析及其在框架开发中的应用 一、引言 在Python中&#xff0c;元类&#xff08;Metaclass&#xff09;是一个高级特性&#xff0c;它允许我们控制类的创建过程。虽然在日常编程中&#xff0c;元类的使用可能并不频繁&#xff0c;但在框架开发、ORM…

莆田市C++专项选拔第二轮题4

题4&#xff1a;变换阵型 【题目描述】 盛隆同学刚学完C的二维数组和函数部分&#xff0c;于是他自己写了2个函数对二维数组进行练习。两个函数如下&#xff1a; int n, a[1005][1005]; // 注意&#xff0c;这里的n和数组a是全局变量 void f1() {for (int i 1; i < n; i)…

Python实现网页保持登录状态的技术方案及实际需求案例

文章目录 1. 使用Cookies直接管理2. 使用Web自动化工具3. 利用API Tokens4. 利用OAuth和其他认证机制5.Python实际需求案例5.1 方法一:多线程实现实现策略示例代码注意事项5.2 方法二:单例实现使用单例模式单例展示配合需求使用单例Python代码实现单例模式的优缺点5.3 方法一…

react 类组件 和 函数组件 声明周期 对比

React 的类组件和函数组件在生命周期方面存在一些差异。以下是它们之间的对比&#xff1a; 类组件的生命周期 React 类组件的生命周期可以分为三个阶段&#xff1a;挂载、更新和卸载。 1、挂载阶段&#xff1a; constructor()&#xff1a;组件实例化时调用&#xff0c;用于…

CNOCR和PaddleOCR提取pdf中文字-个人记录

目录 一、PyMuPDF 二、CNOCR 三、PaddleOCR 四、Tesseract&#xff08;没试&#xff09; 一、PyMuPDF 1.安装PyMuPDF pip install pymupdf 2.pdf转txt样例 import os import datetime import fitz # fitz就是pip install PyMuPDFdef pyMuPDF_fitz(pdfPath):startTime_p…

47岁古天乐唯一承认女友约「御用阿妈」过母亲节

日前关宝慧在IG晒出一张聚会照&#xff0c;并写道&#xff1a;「预祝各位#母亲节快乐&#x1f339;#dinner #happy #friends #好味」相中所见&#xff0c;前TVB金牌监制潘嘉德、卢宛茵、黄&#x28948;莹、黎萨达姆都有出席饭局。 当中黄&#x28948;莹身穿卡其色西装褛&…

blender 为世界环境添加纹理图像

1、打开世界环境配置项 2、点击颜色右侧的黄色小圆&#xff0c;选择环境纹理 3、打开一张天空图像 4、可以通过调整强度/力度&#xff0c;调整世界环境的亮度

《工具分享-整合功能网页》标星5.3k⭐开发人员的在线工具集:it-tools

IT Tools - 为方便开发人员提供的在线工具 部署自己的it-tools: 有两个版本&#xff0c;目前有中文支持。 直接部署使用docker指令获取出来的是英文的&#xff1a; 英文版&#xff1a; docker run -d --name it-tools --restart unless-stopped -p 8080:80 corentinth/it-…

TCP服务器实现将客服端发送的信息广播发送(使用内核链表管理客户端信息)

目录 1.服务器端实现思路 2.服务器端代码 3.客户端代码 4.内核链表代码 5.运行格式 一、服务器端 二、客户端 6.效果 1.服务器端实现思路 Tcp广播服务初始化 等待客户端连接 广播发送 2.服务器端代码 #include "list.h" #include <signal.h> #def…

基于数据挖掘与机器学习揭秘脱发主因

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 基于数据挖掘与机器学习揭秘脱发主因 目录 一、绪论背景描述数据说明内容大概 二、导入包以及数据读取三、数据预览四、探究导致脱发的因素4.1…