高精度算法

简介: 本文详细介绍了高精度算法的实现,涵盖加法、减法、乘法、除法及取模等操作。通过字符串与数组结合的方式,解决了大数运算中超出数据类型范围的问题。每种运算均提供完整的C++代码示例,包括输入处理、位运算模拟、进位/借位逻辑以及结果输出。其中,高精度加法和减法通过逆序存储数字简化计算;乘法利用双重循环模拟手算过程;除法分为低精度和高精度两种情况,分别采用逐位试商与减法模拟;取模则通过逐位累加求余实现。这些方法为处理大规模数值运算提供了有效工具,适用于竞赛编程与实际开发场景。

高精度算法

作者:blue

时间:2024.9

1.高精度加法(整数部分模板)

#include <iostream>
#include <string>
using namespace std;
int a1[1000],a2[1000],ans[1000];
int main()
{
   
    string s1,s2;
    cin>>s1>>s2;//字符串存放大数
    //逆序存放在数组中 
    for(int i=0;i<s1.size();i++) a1[s1.size()-i-1]=s1[i]-'0';
    for(int i=0;i<s2.size();i++) a2[s2.size()-i-1]=s2[i]-'0';
    int len=max(s1.size(),s2.size());
    //先相加 
    for(int i=0;i<len;i++){
   
        ans[i]=a1[i]+a2[i];
    }
    //后处理进位 
    for(int i=0;i<len;i++){
   
        ans[i+1]=ans[i+1]+ans[i]/10;
        ans[i]=ans[i]%10;
    }
    //逆序输出先判断len位为不为0(因为最高位可能进位,所以最长到len位)
    for(int i=len;i>=0;i--){
   
        if(i==len&&ans[len]==0) continue;
        cout<<ans[i];
    }
    return 0;
}

2.高精度减法(整数部分模板)

#include <iostream>
#include <string>
using namespace std;
const int N=1e6+10;
int a1[N],a2[N],ans[N];
int main()
{
   
    string s1,s2;
    cin>>s1>>s2;
    char flag='+';//符号判断 
    //判断两个数谁大谁小,大的那个放置在s1,如果交换了位置,就将符号置为'-'
    if(s1.size()<s2.size()||s1.size()==s2.size()&&s1<s2){
   
        swap(s1,s2);
        flag='-';
    } 
    //倒序存放 
    for(int i=0;i<s1.size();i++) a1[i]=s1[s1.size()-i-1]-'0';
    for(int i=0;i<s2.size();i++) a2[i]=s2[s2.size()-i-1]-'0';
    for(int i=0;i<s1.size();i++){
   
        if(a1[i]<a2[i]){
   //模拟借位的过程 
            a1[i]+=10;
            a1[i+1]--;
        }
        ans[i]=a1[i]-a2[i];
    }
    //注意此处index的值设置为0是有考究的,当是两个相等大数相减的话,那就只用输出1位0 
    int index=0;//找答案中第一个不为0的位置,为输出做准备 
    for(int i=s1.size()-1;i>=0;i--){
   
        if(ans[i]>0){
   
            index=i;
            break;
        }
    } 
    if(flag=='-') cout<<flag;
    for(int i=index;i>=0;i--) cout<<ans[i];
    return 0;
}

3.高精度乘法

image-20241019090817352.png

#include <iostream>
#include <string>
using namespace std;
const int N=1e8+10;
int a1[N],a2[N],ans[N];
int main()
{
   
    string s1,s2;
    cin>>s1>>s2;
    //反转两个数 
    for(int i=0;i<s1.size();i++) a1[i]=s1[s1.size()-i-1]-'0'; 
    for(int i=0;i<s2.size();i++) a2[i]=s2[s2.size()-i-1]-'0'; 
    int len=s1.size()+s2.size();//乘法最终的长度不会长于两个常数长度的和 
    //模拟乘法过程
    for(int i=0;i<s1.size();i++){
   
        for(int j=0;j<s2.size();j++){
   
            ans[i+j]+=a1[i]*a2[j];//注意这里不是赋值语句 
            ans[i+j+1]+=ans[i+j]/10;//进位 
            ans[i+j]=ans[i+j]%10;//保留本位 
        }
    } 
    //消除前导0 
    int index=0;
    for(int i=len;i>=0;i--){
   
        if(ans[i]!=0){
   
            index=i;
            break;
        }
    }
    //倒序输出 
    for(int i=index;i>=0;i--){
   
        cout<<ans[i];
    }
    return 0;
}

4.高精度除法

高精度除以低精度

image-20241019092848282.png

#include <iostream>
#include <string>
using namespace std;
const int N=1e8+10;
int ans[N],a[N];
long long b;
int main()
{
   
    string s;
    long long x=0;//用以承接每次的余数,初始应当为0,因为没有余数,注意这里余数也要开long long 防止余数很大的情况 
    cin>>s>>b;//输入一个高精度数和一个低精度数
    //这里不用倒序存放,因为除法本身就是一个从高位计算到低位的过程 
    for(int i=0;i<s.size();i++) a[i]=s[i]-'0';
    //模拟逐位试商的过程 
    for(int i=0;i<s.size();i++){
   
        ans[i]=(x*10+a[i])/b;
        x=(x*10+a[i])%b;
    }
    int index=0;
    //消除前导0,注意此处,index不能超过被除数的长度 
    while(ans[index]==0&&index<s.size()) index++;
    for(int i=index;i<s.size();i++) cout<<ans[i];
    if(index==s.size()) cout<<"0";//如果index等于被除数的长度,那么说明商就为0,要打印0
    //cout<<" "<<x;//有需要还可以打印余数 
    return 0;
}

高精度除以高精度

高精度除高精度要用减法模拟除法

image-20241019145033990.png

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int N=1e6+10;
int a[N],b[N],c[N],tmp[N];
void init(int a[]){
   
    string s;
    cin>>s;
    a[0]=s.size();//a[0]存储字符串的长度 
    for(int i=1;i<=s.size();i++) a[i]=s[s.size()-i]-'0';//逆序存储 
}
void print(int a[]){
   
    if(a[0]==0){
   
        cout<<"0";
        return;
    }
    for(int i=a[0];i>0;i--) cout<<a[i];
    return;
}
int compare(int a[],int b[]){
   //比较两个数的大小,如果a大返回1,如果b大返回-1,一样大返回0 
    if(a[0]>b[0]) return 1;
    if(a[0]<b[0]) return -1;
    for(int i=a[0];i>0;i--){
   
        if(a[i]>b[i]) return 1;
        if(a[i]<b[i]) return -1; 
    }
    return 0;
}
void minu(int a[],int b[]){
   //高精度减法 
    for(int i=1;i<=a[0];i++)
    {
   
        if(a[i]<b[i]){
   
            a[i]+=10;
            a[i+1]--;
        }
        a[i]=a[i]-b[i];
    }
    while(a[a[0]]==0&&a[0]>0) a[0]--;//删除前导0 
    return; 
}
void numcpy(int b[],int tmp[],int n){
   //
    for(int i=1;i<=b[0];i++) tmp[i+n]=b[i];
    tmp[0]=b[0]+n;
}
int main()
{
   
    init(a);
    init(b);
    c[0]=a[0]-b[0]+1;//两位数相除,商最长的长度 
    if(c[0]<0) c[0]=0;
    for(int i=c[0];i>=1;i--){
   
        memset(tmp,0,sizeof(tmp));
        numcpy(b,tmp,i-1);//减法模拟除法,扩展减数,和被减数一样长 
        while(compare(a,tmp)>=0){
   //减干净 
            c[i]++;
            minu(a,tmp);
        }
    }
    while(c[c[0]]==0&&c[0]>0) c[0]--;//消去前导0 
    print(c);
    //print(a);//余数 
}

5.高精度取模

蛐蛐取mod,直接拿下

4.字符串加法【算法赛】 - 蓝桥云课 (lanqiao.cn)

#include <iostream>
#include <string>
#define int long long
using namespace std;
const int mod=1e9+7;
long long long_mod(string a)
{
   
  int ans=0;
  for(int i=0;i<a.size();i++){
   
    ans=(ans*10+(a[i]-'0'))%mod;
  }
  return ans;
}

signed main()
{
   
  string a,b,res;
  cin>>a>>b;
  res=a+b;
  cout<<long_mod(res);
  return 0;
}

6.高精度

第十五届蓝桥杯C/C++B组题解——R格式_第十五届蓝桥杯c语言b组答案-CSDN博客

目录
相关文章
|
消息中间件 存储 NoSQL
深入Redis消息队列:Pub/Sub和Stream的对决【redis第六部分】
深入Redis消息队列:Pub/Sub和Stream的对决【redis第六部分】
1234 0
|
存储 Shell 网络安全
|
弹性计算 Linux 数据库
快速用Discuz搭建论坛网站教程
Discuz! 是全球成熟度最高、覆盖率最大的论坛网站软件系统之一,被200多万网站用户使用,本文教你一步一步快速用阿里云免费的Discuz官方系统搭建论坛网站。
45683 0
|
存储 算法 C++
高精度算法(加、减、乘、除,使用c++实现)
高精度算法(加、减、乘、除,使用c++实现)
3755 0
高精度算法(加、减、乘、除,使用c++实现)
|
9月前
|
机器学习/深度学习 算法 数据可视化
基于YOLOv8的无人机航拍树木目标检测系统|精准识别【含完整训练源码+部署教程】
本项目基于YOLOv8构建了一个支持无人机航拍图像的棕榈树目标检测系统,兼具高精度识别能力与友好的图形化交互界面。通过结合PyQt5,实现了图片、视频、摄像头等多种输入方式的检测体验,极大提升了项目的实用性与可扩展性。
基于YOLOv8的无人机航拍树木目标检测系统|精准识别【含完整训练源码+部署教程】
|
算法 Go
【LeetCode 热题100】23:合并 K 个升序链表(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 23——合并 K 个升序链表的两种解法:优先队列(最小堆)和分治合并。题目要求将多个已排序链表合并为一个升序链表。最小堆方法通过维护节点优先级快速选择最小值,;分治合并则采用归并思想两两合并链表。文章提供了 Go 语言实现代码,并对比分析两种方法的适用场景,帮助读者深入理解链表操作与算法设计。
457 10
|
存储 算法 Java
【DFS(深度优先搜索)详解】看这一篇就够啦
本文介绍了深度优先搜索(DFS)算法及其应用。DFS从某个顶点出发,深入探索图的每条路径,直到无法前进为止,然后回溯。文章详细解释了DFS的基本思想,并通过示例图展示了其执行过程。此外,文中还探讨了三种枚举方式:指数型枚举、排列型枚举和组合型枚举,并提供了具体的代码实现。最后,文章通过几道练习题帮助读者更好地理解和应用DFS算法。
10922 19
【DFS(深度优先搜索)详解】看这一篇就够啦
|
算法
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
这篇文章介绍了动态规划算法中解决最大上升子序列问题(LIS)的方法,包括问题的描述、动态规划的步骤、状态表示、递推方程、计算最优值以及优化方法,如非动态规划的二分法。
434 0
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)