news 2026/4/23 14:27:39

【基础算法】高精度运算深度解析与优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【基础算法】高精度运算深度解析与优化

🔭个人主页:散峰而望

《C语言:从基础到进阶》《编程工具的下载和使用》《C语言刷题》《算法竞赛从入门到获奖》《人工智能》《AI Agent》

愿为出海月,不做归山云

🎬博主简介

【算法竞赛】高精度运算深度解析与优化

  • 前言
  • 高精度
    • 1. 高精度加法
    • 2. 高精度减法
    • 3. 高精度乘法
    • 4. 高精度除法
  • 结语

前言

算法竞赛中经常需要处理超出标准数据类型范围的整数运算,例如大数阶乘、斐波那契数列的大项计算或密码学相关题目。标准数据类型如 int 或 long long 的存储范围有限,无法直接处理上百位的数字运算。高精度运算通过模拟人工计算过程,将大数拆分为数组或字符串逐位处理,成为解决此类问题的核心方法。

高精度

当数据的值特别大,各种类型都存不下的时候,此时就要用高精度算法来计算加减乘除:

  • 先用字符串读入这个数,然后用数组逆序存储该数的每一位;
  • 利用数组,模拟加减乘除运算的过程。

高精度算法本质上还是模拟算法,用代码模拟小学列竖式计算加减乘除的过程。

之所以用数组逆序存储该数的每一位,是因为我们计算的是从个位开始,而逆序正好是从下标 0 位开始,模拟最低位到最高位*。同时处理进位时,正序的话,进位不知道往什么位置进位。

1. 高精度加法

高精度加法

算法原理:

模拟小学「列竖式」计算「两数相加」的过程。

  1. 用字符串读入数据;
  2. 将字符串的每一位拆分,逆序放在数组中;
x=" 4 3 9 "下标012inta[]=[9,3,4]下标012
  1. 模拟列竖式计算的过程:
    a. 对应位累加 -->x
    b. 处理进位 -->x / 10
    c. 处理余数 -->x % 10

  1. 处理结果的位数。

核心代码:

voidadd(intc[],inta[],intb[]){for(inti=0;i<lc;i++){c[i]+=a[i]+b[i];c[i+1]=c[i]/10;c[i]%=10;}if(c[lc])lc++;}

参考代码:

#include<iostream>usingnamespacestd;constintN=1e6+10;inta[N],b[N],c[N];intla,lb,lc;voidadd(intc[],inta[],intb[]){for(inti=0;i<lc;i++){c[i]+=a[i]+b[i];c[i+1]=c[i]/10;c[i]%=10;}if(c[lc])lc++;}intmain(){string x,y;cin>>x>>y;//拆分每一位,逆序放在数组中la=x.size();lb=y.size();lc=max(la,lb);//先指定lc的最大的数范围后,如果超过就再加for(inti=0;i<la;i++)a[la-1-i]=x[i]-'0';for(inti=0;i<lb;i++)b[lb-1-i]=y[i]-'0';//模拟加法过程add(c,a,b);//输出for(inti=lc-1;i>=0;i--){cout<<c[i];}return0;}

2. 高精度减法

高精度减法

算法原理:

模拟小学「列竖式」计算「两数相减」的过程。

  1. 用字符串读入数据;
  2. 判断两个数的大小,让较大的数在前。注意字典序 vs 数的大小:
    a. 位数相等:按字典序比较;
    b. 位数不等:按照字符串的长度比较。
    即先比较长度再比较字典序,不然会出现下面这种情况
数:101>99字符串:"101"<"99"
  1. 将字符串的每一位拆分,逆序放在数组中;
  2. 模拟列竖式计算的过程:
    a. 对应位求差;
    b. 处理借位;
  3. 处理前导零:因为减数完位数可能会往后退,比如十位退到个位,此时在十位的没有存储其他东西,就要把此处的空间释放掉。

核心代码:

voidsub(intc[],inta[],intb[]){for(inti=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--;}

参考代码:

#include<iostream>usingnamespacestd;constintN=1e6+10;inta[N],b[N],c[N];intla,lb,lc;// 比大小boolcmp(string&x,string&y){// 先比较长度if(x.size()!=y.size())returnx.size()<y.size();// 再按照字典序的方式比较returnx<y;}voidsub(intc[],inta[],intb[]){for(inti=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--;}intmain(){string x,y;cin>>x>>y;// 比大小if(cmp(x,y)){swap(x,y);cout<<'-';}//拆分每一位,然后逆序放在数组中la=x.size();lb=y.size();lc=max(la,lb);for(inti=0;i<la;i++)a[la-i-1]=x[i]-'0';for(inti=0;i<lb;i++)b[lb-i-1]=y[i]-'0';//模拟减法的过程sub(c,a,b);// c = a - b//输出for(inti=lc-1;i>=0;i--)cout<<c[i];return0;}

3. 高精度乘法

高精度乘法

算法原理:

无进位相乘再相加:

  • 还是「列竖式」,但是每一位相乘的时候不考虑进位,直接把乘的结果放在对应位上;
  • 等到所有对应位置「乘完」并且「累加完」之后,「统一处理进位」。

如下图所示:

即可理解为下标 + 下标 = 对应下标相乘位置=>c[i + j] += a[i] * b[j]

  1. 0 下标和 0 下标相乘在 0 下标位置,和 1 下标相乘在 1 下标位置,和 2 下标相乘在 2 下标位置
  2. 1 下标和 0 下标相乘在 1 下标位置,和 1 下标相乘在 2 下标位置,和 2 下标相乘在 3 下标位置
  3. 2 下标和 0 下标相乘在 2 下标位置,和 1 下标相乘在 3 下标位置,和 2 下标相乘在 4 下标位置

具体解法:

  1. 用字符串读入数据;
  2. 将字符串的每一位拆分,逆序放在数组中;
  3. 模拟无进位相乘再相加的过程:
    a. 对应位求乘积;
    b. 乘完之后处理进位;
    c. 处理余数;
  4. 处理前导零。

核心代码:

voidmul(intc[],inta[],intb[]){// 无进位相乘,然后相加for(inti=0;i<la;i++){for(intj=0;j<lb;j++){c[i+j]+=a[i]*b[j];}}// 处理进位for(inti=0;i<lc;i++){c[i+1]+=c[i]/10;c[i]%=10;}// 处理前导零while(lc>1&&c[lc-1]==0)lc--;}

参考代码:

#include<iostream>usingnamespacestd;constintN=1e6+10;inta[N],b[N],c[N];intla,lb,lc;voidmul(intc[],inta[],intb[]){// 无进位相乘,然后相加for(inti=0;i<la;i++){for(intj=0;j<lb;j++){c[i+j]+=a[i]*b[j];}}// 处理进位for(inti=0;i<lc;i++){c[i+1]+=c[i]/10;c[i]%=10;}// 处理前导零while(lc>1&&c[lc-1]==0)lc--;}intmain(){string x,y;cin>>x>>y;//拆分每一位,逆序放在数组中la=x.size();lb=y.size();lc=la+lb;for(inti=0;i<la;i++)a[la-1-i]=x[i]-'0';for(inti=0;i<lb;i++)b[lb-1-i]=y[i]-'0';//模拟乘法的过程mul(c,a,b);// c = a * b//输出for(inti=lc-1;i>=0;i--)cout<<c[i];return0;}

4. 高精度除法

高精度除法

算法原理:

模拟小学「列竖式」计算「两数相除」的过程(注意:我们这里是「高精度 ÷ 低精度」,而「高精度 ÷ 高精度」题目比较少见,其模拟方式是用减法方法,可以下去自行了解)

定义一个指针 i 从「高位」遍历被除数,一个变量 t 标记当前「被除的数」,记除数是 b

  • 更新一个当前被除的数t = t × 10 + a[i]
  • t / b表示这一位的商,t % b表示这一位的余数
  • 用 t 记录这一次的余数,遍历到下一位的时候重复上面的过程

被除数遍历完毕之后,t 里面存的就是余数,但是商可能存在前导 0 ,注意清空。

核心代码:

voidsub(intc[],inta[],intb){LL t=0;// 标记每次除完之后的余数for(inti=la-1;i>=0;i--){// 计算当前的被除数t=t*10+a[i];c[i]=t/b;t%=b;}// 处理前导 0while(lc>1&&c[lc-1]==0)lc--;}

参考代码:

#include<iostream>usingnamespacestd;constintN=1e6+10;typedeflonglongLL;inta[N],b,c[N];intla,lc;voidsub(intc[],inta[],intb){LL t=0;// 标记每次除完之后的余数for(inti=la-1;i>=0;i--){// 计算当前的被除数t=t*10+a[i];c[i]=t/b;t%=b;}// 处理前导 0while(lc>1&&c[lc-1]==0)lc--;}intmain(){string x;cin>>x>>b;la=x.size();for(inti=0;i<la;i++)a[la-1-i]=x[i]-'0';// 模拟除法的过程lc=la;sub(c,a,b);// c = a / bfor(inti=lc-1;i>=0;i--)cout<<c[i];return0;}

结语

高精度运算在算法竞赛中占据重要地位,尤其在处理大整数运算时不可或缺。通过模拟手工计算的方法,高精度加法、减法、乘法和除法能够突破语言原生数据类型的限制,实现任意位数的精确计算。

掌握高精度运算的核心在于理解逐位处理与进位借位的逻辑,并优化存储与计算率。在实际竞赛中,灵活运用高精度算法可解决大数阶乘、大数取模、高精度浮点运算等复杂问题。

进一步优化高精度运算可结合快速傅里叶变换(FFT)加速乘法,或采用压位存储减少计算次数。持续练习与深入理解高精度算法,能显著提升解决复杂数学问题的力。

愿诸君能一起共渡重重浪,终见缛彩遥分地,繁光远缀天

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 19:23:10

看完就想试!Whisper-large-v3语音转文字效果展示

看完就想试&#xff01;Whisper-large-v3语音转文字效果展示 你有没有过这样的经历&#xff1a;录了一段会议音频&#xff0c;想快速整理成文字&#xff0c;结果用几个主流工具试下来&#xff0c;不是漏字就是错别字连篇&#xff0c;中文夹英文的专有名词全乱套&#xff1b;或…

作者头像 李华
网站建设 2026/4/22 4:24:26

ESP32开发板安装失败全面解决方案:从诊断到预防的完整指南

ESP32开发板安装失败全面解决方案&#xff1a;从诊断到预防的完整指南 【免费下载链接】arduino-esp32 Arduino core for the ESP32 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 ESP32开发板安装失败是困扰许多物联网开发者的常见问题&#xff0c;…

作者头像 李华
网站建设 2026/4/19 14:08:51

中文逆文本标准化利器|FST ITN-ZH镜像应用全解析

中文逆文本标准化利器&#xff5c;FST ITN-ZH镜像应用全解析 你有没有遇到过这样的场景&#xff1a; 刚整理完一份会议录音转写的文字稿&#xff0c;发现里面全是“二零二三年十一月十五日”“下午三点四十五分”“一百二十三点五元”——这些表达在口语中自然&#xff0c;但放…

作者头像 李华
网站建设 2026/4/23 13:17:50

3步解锁AI绘画:让创意落地的Blender插件全攻略

3步解锁AI绘画&#xff1a;让创意落地的Blender插件全攻略 【免费下载链接】AI-Render Stable Diffusion in Blender 项目地址: https://gitcode.com/gh_mirrors/ai/AI-Render AI绘图技术正通过Blender插件实现技术民主化&#xff0c;使数字创作者无需深厚技术背景即可将…

作者头像 李华
网站建设 2026/4/21 1:16:35

游戏自动化工具:智能助手助力效率提升完全指南

游戏自动化工具&#xff1a;智能助手助力效率提升完全指南 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸上锁合成 自动肉鸽 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-waves 游戏自动化工具…

作者头像 李华