news 2026/3/8 5:00:02

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

作者头像

张小明

前端开发工程师

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/3/8 0:45:05

如何合法高效获取电子教材?教育资源管理全攻略

如何合法高效获取电子教材&#xff1f;教育资源管理全攻略 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具 项目地址: https://gitcode.com/GitHub_Trending/tc/tchMaterial-parser 教育资源获取挑战&#xff1a;数字时代的教学困境 想象…

作者头像 李华
网站建设 2026/3/7 15:43:38

升级Paraformer后:科哥镜像带来丝滑识别新体验

升级Paraformer后&#xff1a;科哥镜像带来丝滑识别新体验 1. 为什么这次升级值得你立刻尝试 你有没有遇到过这样的场景&#xff1a;会议录音转文字&#xff0c;关键人名和专业术语全错了&#xff1b;客户语音留言识别成一堆乱码&#xff1b;实时语音输入卡顿半天才出结果&am…

作者头像 李华
网站建设 2026/3/6 12:44:52

如何永久保存珍贵对话?这款工具让数字记忆永不褪色

如何永久保存珍贵对话&#xff1f;这款工具让数字记忆永不褪色 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatMs…

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

3步快速获取电子课本:tchMaterial-parser工具完整使用指南

3步快速获取电子课本&#xff1a;tchMaterial-parser工具完整使用指南 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具 项目地址: https://gitcode.com/GitHub_Trending/tc/tchMaterial-parser 在数字化学习时代&#xff0c;获取优质电子…

作者头像 李华