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

目录

高精度

引入

使用场景

实现原理

高精度加法

数据存储

加法实现

总代码

高精度减法

与加法的不同点:

总代码

高精度乘法

总代码

高精度除法

总结

总注意点

减法注意点

高精度

引入

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

使用场景

高精度算法(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.xdnf.cn/news/1421076.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

使用 CloudFlare 后如何才能不影响搜索引擎蜘蛛爬虫

今天,明月给大家再次详细讲解一下,明月在使用 CloudFlare 后如何才能不影响搜索引擎蜘蛛爬虫对站点的抓取,因为这是很多首次使用 CloudFlare 的站长们容易忽略和触犯的问题,并不是 CloudFlare 不友好,而是 CloudFlare 的防火墙(WAF)实在是太给力。其实在【CloudFlare 如…

SQLZOO:The JOIN operation

数据表&#xff1a;game-gaol-eteam game idmdatestadiumteam1team210018 June 2012National Stadium, WarsawPOLGRE10028 June 2012Stadion Miejski (Wroclaw)RUSCZE100312 June 2012Stadion Miejski (Wroclaw)GRECZE100412 June 2012National Stadium, WarsawPOLRUS... goal …

每日OJ题_贪心算法四④_力扣397. 整数替换

目录 力扣397. 整数替换 解析代码 力扣397. 整数替换 397. 整数替换 难度 中等 给定一个正整数 n &#xff0c;你可以做如下操作&#xff1a; 如果 n 是偶数&#xff0c;则用 n / 2替换 n 。如果 n 是奇数&#xff0c;则可以用 n 1或n - 1替换 n 。 返回 n 变为 1 所需…

最大子矩阵:前缀和、动态规划

最近在学习动态规划&#xff0c;在牛客上刷题时碰到了这一题。其实最初的想法是暴力和前缀和&#xff0c;但是时间复杂度极高&#xff0c;需要套4层循环。后来去网上搜了一下相关的题解和做法&#xff0c;进而了解到了前缀和&#xff0b;线性动态规划的做法。但是在成功做出这题…

排除对象属性序列化的三种方式

说明&#xff1a;在项目里&#xff0c;经常可以看到以下日志内容&#xff0c;将对象序列化后直接打印出来&#xff0c;观察对象数据&#xff0c;判断当前处理逻辑正确与否。 &#xff08;以下信息来自&#xff1a;https://www.tl.beer/randbankcard.html生成器&#xff0c;信息…

python跟C++选哪个?

选择使用Python还是C取决于你的具体需求和项目背景。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 在通信工程行业…

第六节笔记及作业----Lagent AgentLego 智能体应用搭建

关于 Agent 的相关理论 大语言模型存在一些局限性&#xff0c;比如会出现幻觉问题、有时效性问题以及可靠性问题。智能体的定义是具备感知、决策和行动能力的实体。智能体主要由感知部分、大脑部分和动作部分组成。智能体有多种类型&#xff0c;如 ReAct 类型&#xff08;侧重…

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

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

视频打赏系统源码

地球号&#xff1a;xiaobao0214520(WX) 支付对接&#xff0c;盒子推广&#xff0c;域名防封&#xff0c;等一系列功能皆为正常&#xff0c;后台账号密码:地球号&#xff1a;xiaobao0214520(WX)&#xff0c;测试网站,可以定制哦支付对接&#xff0c;盒子推广&#xff0c;域名防…

免费思维13招之七:空间型思维

免费思维13招之七:空间型思维 本篇给你带来的是空间型思维。 空间型思维,具体分为内部空间型思维和外部空间型思维。 什么叫内部空间型思维呢? 内部空间型就是充分利用现有空间或资源为社会提供免费服务,积累人气,增加流量,从而带动消费。 为什么你生意不好?为什么你…

python数据分析——matplotlib可视化基础

参考资料&#xff1a;活用pandas库 # 导入库 import pandas as pd import matplotlib.pyplot as plt # 导入数据 anscombepd.read_csv(r"...\seaborn常用数据案例\anscombe.csv") anscombe.head() 大多数基本图表的名字以plt.plot开头。 # 创建数据子集 # 只包含数…

图片转word如何转换?

要将图片转换为Word文档&#xff0c;你可以使用以下方法之一&#xff1a; 以上这些方法都可以帮助你将图片中的文本转换为可编辑的Word文档&#xff0c;你可以根据自己的喜好和需求选择其中一种方法来操作。 使用OCR软件或在线工具&#xff1a;有许多OCR&#xff08;Optical Ch…

【Spring】验证 @ServerEndpoint 的类成员变量线程安全

文章目录 前言猜想来源验证方法Controller 的情况ServerEndpoint 的情况 后记 前言 最近有 websocket 的需求。探索 ServerEndpoint 的类成员变量特点。 这里类比 Controller 讨论 ServerEndpoint 类成员变量是否线程安全。 猜想来源 网上的教程大多数都这么展示程序&#…

Ardupilot开源代码之Rover上路 - 后续1

Ardupilot开源代码之Rover上路 - 后续1 1. 源由2. 问题汇总2.1 问题1&#xff1a;飞控选择2.2 问题2&#xff1a;飞控安装位置和固定2.3 问题3&#xff1a;各种插头、插座配套2.4 问题4&#xff1a;分电板缺陷2.5 问题5&#xff1a;电机编码器接线及正反向问题2.6 问题6&#x…

树莓派python开发

树莓派自带thonny 点亮LED灯 import RPi.GPIO as GPIO import time# 设置GPIO模式为BCM GPIO.setmode(GPIO.BCM)# 设置LED引脚 led_pin 18# 设置LED引脚为输出 GPIO.setup(led_pin, GPIO.OUT)# 点亮LED GPIO.output(led_pin, GPIO.HIGH)# 延时2秒 time.sleep(2)# 关闭LED GPI…

电商核心技术揭秘55:社群与粉丝经济的结合

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 电商技术揭秘四十一&#xff1a;电商平台的营销系统浅析 电商技术揭秘四十二&#…

Jboss 反序列化 CVE-2017-12149

一、漏洞简介 JBoss是一个管理EJB的容器和服务器&#xff0c;支持EJB 1.1、EJB 2.0和EJB3的规范。在/invoker/readonly路径下&#xff0c;攻击者可以构造序列化代码传入服务器进行反序列化,由于没有对反序列化操作进行任何检测&#xff0c;导致攻击者可以执行任意代码。 而jbo…

重发布和路由策略实验(课堂练习)

需求&#xff1a; 将1.1.1.0/24网段&#xff08;不在OSPF中&#xff09;重发布到网络中&#xff0c;不允许出现次优路径&#xff0c;实现全网可达。 需求分析&#xff1a; 1、在R1上重发布1.1.1.0/24网段&#xff0c;但是需要过滤192.168.12.0/24和192.168.13.0/24 2、在R2和R3…

考研数学|强化阶段怎么刷《660》《880》《1000》?

强化阶段想要刷好题&#xff0c;首先要选一本适合自己的题集&#xff01; 一般在强化阶段&#xff0c;大家用多个最多的题集就是660题&#xff0c;880题还有1000题 660题的特点是只训练客观题&#xff0c;虽然题目的质量很高&#xff0c;但是训练面还是比较窄 880题是综合训…

关于DDD和COLA的一些总结和思考

1|0思维&#xff1a;面向对象和面向过程 领域驱动设计本质上是讲的面向对象&#xff0c;但是谈面向对象&#xff0c;始终无法绕开面向过程&#xff0c;所以我们先好好说一下面向过程和面向对象这两个概念。 什么是面向过程呢&#xff0c;其实就是我们学习编程时最初被植入的逻辑…