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

高精度

前言

某同学:你为啥不写高精度呢?

我:那玩意儿有啥讲的,又不是啥重要的知识点。

某同学:万一要用呢?

我:……

我:那就等要用了再说。

好的前几天真写到要用高精度的题了。

我说我无中生题你信吗。

高精度

高精度这个东西,本质上就是一种模拟,它通过模拟人列竖式计算的过程来实现计算大数。

你比如说正常情况下我们有 intlong long 两种类型,实在不行还有 unsigned__int128 类型。但是就算是 __int128,也只能计算 \(-2^{127}\sim2^{127}-1\) 之间的数,换算成十进制大概是 \(39\) 位。

那如果现在我要算 \(100\) 位、\(1000\) 位,甚至 \(10000\) 位的十进制加减乘除法怎么办呢?显然我们人在计算大数的加减乘除时用的是竖式,那我们可不可以模仿竖式的方法写出一套加减乘除法呢?

高精度加法、减法

首先讲最简单的高精度加法与减法。因为通过竖式我们能观察到:加法与减法本质上就是每一位对位相加减,唯一的问题是进位与借位。

搞懂这个东西的原理过后,那一切就都很简单了:我们只需要定义一个数组,然后让数组的每一位存一位数字,这样加法就是把每一位相加,减法就是把每一位相减。

现在来说说进位和借位。显然进位是从低位往高位进位,借位也是从低位往高位借位。所以我们只需要将整个数组从低位往高位循环一遍并做处理。

当然,如果说目前的最高位还能进位,那么我们就要适当扩展位数了。如果前面有过多的前导 \(0\),也需要缩小位数。

为了更方便的扩展位数,我们一般会把最高位放在最后,而最低位放在最前面,也就是把整个数倒过来。

代码:

for(int i=1;i<=nc;i++)
{c[i]=a[i]+b[i];//减法改成 a[i]-b[i] 就行了if(c[i]>9)//进位{c[i+1]+=c[i]/10;c[i]%=10;}if(c[i]<0)//借位 {c[i+1]--;c[i]+=10;}
}
while(c[nc]>9)//高位进位
{c[nc+1]+=c[nc]/10;c[nc]%=10;nc++;
}
while(c[nc]==0&&nc>1)//去掉前导 0,nc>1 是防止答案是 0 时会去掉这个 0
{nc--;
}

高精度乘法

关于高精度乘法,显然我们也可以通过竖式找规律。这里跳过这一环节。

最终我们会发现:\(a_i\times b_j\) 的结果会被保存到 \(c_{i+j-1}\)(从 \(1\) 开始,如果从 \(0\) 开始就没有 \(-1\)),因此我们可以这么写:

for(int i=1;i<=na;i++)
{for(int j=1;j<=nb;j++){c[i+j-1]+=a[i]*b[j];//这里记得用 += if(c[i+j-1]>9)//进位 {c[i+j]+=c[i+j-1]/10;c[i+j-1]%=10;}}
}
while(c[nc]>9)//高位进位
{c[nc+1]+=c[nc]/10;c[nc]%=10;nc++;
}

显然是我已经懒得讲了。

高精度除法

高精度除法这个稍微有点难办了,因为虽然除法有一种理解方式就是被除数不断减去除数,但是你不知道答案有多大,因此我们还是要从竖式上入手。

我们会发现在竖式上,除法其实是先将当前的余数求出来,然后除以除数得到当前这一位的商,然后再计算当前这一位的余数继承到下一位,然后重复这个过程。

稍微有点抽象,我来举个例子手动具象化一下。比如你让算 \(12345\div5\) 等于多少,首先一开始你的余数是 \(0\),然后将这个余数与你的第一位拼接在一起,就变成了 \(1\),然后你发现 \(1\div5=0\)\(1\),所以第一位答案是 \(0\),余数是 \(1\)

接着你将余数 \(1\) 与第二位拼在一起,就成了 \(12\),然后你发现 \(12\div5=2\)\(2\),所以第二位答案是 \(2\),余数是 \(2\)

接着你将余数 \(2\) 与第三位拼在一起,就成了 \(23\),然后你发现 \(23\div5=4\)\(3\),所以第三位答案是 \(4\),余数是 \(3\)

接着你将余数 \(3\) 与第四位拼在一起,就成了 \(34\),然后你发现 \(34\div5=6\)\(4\),所以第四位答案是 \(6\),余数是 \(4\)

接着你将余数 \(4\) 与第五位拼在一起,就成了 \(45\),然后你发现 \(45\div5=9\)\(0\),所以第五位答案是 \(9\),余数是 \(0\)

因此我们得到最终答案:\(12345\div5=2469\)\(0\)

好的这样我们就把一个庞大的问题转化成了一个个小问题。现在唯一的问题是每一次除法我该怎么做?这个分两种情况。

高精除以低精

也就是说一个非常大的数除以一个非常小的数,这时每一次除法是可以直接计算的,因此每次算答案直接用当前余数除以除数就行了。

代码:

int v=0;
for(int i=na;i>=1;i--)
{v=v*10+a[i];//把之前余数与当前位拼接c[i]=v/b;//算商v%=b;//取余数
}
while(c[nc]==0&&nc>1)//去掉前导 0
{nc--;
}

高精除以高精

一般情况下上面那种已经够用了,但是不乏有些丧心病狂的出题人,非要让你写一个高精除以高精,这时该咋办呢?

显然,我们没法直接做除法,那我们可以把每次除法转化成另一种东西——减法。

我们再用一个高精度数存当前的余数,然后你会发现一开始的乘法和加法是好处理的。

接下来我们每次判断当前的余数是否大于等于除数,如果是那么就在答案当前位上加一,然后给余数减去一次除数,直到不满足条件为止。

因为每一位的数最大是 \(9\),所以你的循环次数必然不会超过 \(10\) 次。

这个我好像没写过,大家可以尝试一下。

压位

压位算是高精度的一个技巧,要理解压位我们需要把高精度放在一个更高的角度来看。

从更高的角度来看:高精度实际上就是在模拟一次十进制计算,那如果我们将这个进制切换一下,对应到高精度上是什么呢?你会发现你每一位存的数都是按照这个新的进制来的,于是压位变诞生了。

我们会发现之前一位一位存储的方式效率太低了,那么我们可以直接从十进制变成十亿进制,也就是把进制从 \(10\) 改成 \(10^9\),那么对应上去就是说:你把原本 \(9\) 位才能计算的东西缩小到了 \(1\) 位就能计算出来,因此总时间复杂度就会除以一个 \(9\) 的常数。

当然你可以把进制改成各种各样的,就会除以不同的常数。

代码我懒得给了,实际上就是把上面的代码修改一下进制就行了。

http://www.jsqmd.com/news/1342073/

相关文章:

  • 基于混合极限学习机HKELM+NSGAII多目标优化算法的工艺参数优化【四目标】附Matlab 代码
  • 大模型 LLM 全栈技术深度解析:从 Transformer 底层原理到 RAG 与 Agent 系统架构
  • 070、YOLOv11改进-动态标签分配策略即插即用改进涨点方案
  • Daft开发者指南:贡献代码与扩展功能的最佳实践
  • 2026实力之选:房屋建筑工程监理资质甲级代办服务公司深度解析 - 卓企推荐
  • OpenClaw 采集效率优化:并发控制、增量采集策略与服务器友好型设计
  • SGMSE项目深度解析:基于分数生成模型的语音增强与去混响技术革命
  • VisualCppRedist AIO:3分钟解决Windows软件运行库问题的终极方案
  • DownKyi终极指南:5步掌握B站视频高效下载的专业技巧
  • MLFeatureSelection:基于自定义算法、损失函数与验证方法的终极特征选择工具
  • Git仓库损坏谜案:多会话并发checkpoint的竞态条件与修复实战
  • 【图像去噪】基于ADMM算法实现遥感图像去条纹噪声(含SSIM PSNR)附Matlab代码
  • CDP持续数据保护IO层技术解析:从块设备驱动到秒级RPO的实现原理
  • MySQL事务日志系统:undo log、redo log与bin log深度解析
  • 杭州市淳安县GEO服务商代理加盟选型靠谱本地推荐:源头厂商、合伙人权益与本地市场怎么一次看清? - 小随科技
  • 属于上岸党偷摸吃好的这5个神仙功能,是时候公开了
  • 提升LLM吞吐量的秘密武器:KVzap-linear-Llama-3.1-8B-Instruct实战案例分享
  • 多表智能生成技术解析与优化实践
  • KVzap-linear-Llama-3.1-8B-Instruct与传统方法对比:为什么它是LLM推理的游戏规则改变者?
  • 2026年新会专利布局怎么选?政策补贴、申请标准、机构适配全解析 - 米諾
  • 如何快速上手WeTextProcessing?3分钟掌握文本归一化核心功能
  • go-astisub CLI命令详解:轻松实现字幕转换、同步与合并
  • 会话session概念解析
  • 南京市秦淮区GEO服务商代理加盟选型靠谱本地推荐:本地创业者怎么挑到源头厂商和真权益? - 企业新闻快传
  • Unity多人游戏开发:UGS集成与Boss Room架构深度解析
  • HarmonyOS 应用开发《掌上英语》第35篇:媒体资源变更通知相关指导
  • 椰林海鲜码头企业文化是什么 - 松梢月冷
  • 如何在C项目中快速集成µnit?5分钟上手教程
  • 如何通过scene-editor构建专业级3D场景:从模块化架构到可视化实践
  • 从ChatML到工具调用:LFM2.5-2.6B对话模板深度解析