参考:https://blog.csdn.net/actioncms/article/details/105148549
一、本质
高精度算法的本质在于将复杂变为简单
实现的原理是小学学过的列式计算
将每一位进行逐步运算
二、代码
高精加
/*====================================== 高精度加法 不考虑负数(高精减来处理负数) 字符接收再转为整数数组 注意颠倒,注意消除前置0 核心在于 a 数组 + b数组 = c数组 核心代码为: c[i]+=a[i]+b[i]; c[i+1]=c[i]/10; c[i]=c[i]%10; =======================================*/ #include <iostream> using namespace std; string s1,s2; int a[1000]; int b[1000]; int c[1001]; int main() { cin >>s1 >>s2; int la=s1.length(); int lb=s2.length(); for (int i=0;i<la;i++) { a[la-i] = s1[i] - '0'; //转化接收 } for (int i=0;i<lb;i++) { b[lb-i] = s2[i] - '0'; } int lc = max(la,lb)+1; //c数组的长度 for (int i=1;i<=lc;i++) { c[i] += a[i] + b[i]; //核心代码 c[i+1] = c[i]/10; c[i] = c[i]%10; } if (c[lc]==0 && lc>0) lc--; //消除前置0 for (int i=lc;i>0;i--) { cout <<c[i]; } return 0; }
高精减
/*========================================= 高精度减法 输入的也是两个正数 flag是对正负号的跟踪判断 comp函数还是需要深入理解下(判断是否换位) ==========================================*/ #include <iostream> #include <string> using namespace std; string s1,s2; string s3; bool flag=0; int a[10100],b[10100],c[10100]; bool comp(string a,string b) { int la=a.length(); int lb=b.length(); if (la!=lb) return la>lb; else { for (int i=0;i<la;i++) { if (a[i]!=b[i]) { return a[i]>b[i]; break; } } } } int main() { cin >>s1 >>s2; if (!comp(s1,s2)) { s3=s1; s1=s2; s2=s3; flag=1; //若换位则改变 flag } int la=s1.length(); int lb=s2.length(); for (int i=0;i<la;i++) { a[la-i]=s1[i]-'0'; } for (int i=0;i<lb;i++) { b[lb-i]=s2[i]-'0'; } int lc=max(la,lb); //与加法不同 c 数组的长度最多是 a,b中较长那个 for (int i=1;i<=lc;i++) { if (a[i]<b[i]) //借位判断 { a[i+1]--; //不够则向上位借1 a[i]+=10; //本位+10 } c[i]=a[i]-b[i]; } while (c[lc]==0&&lc>1) lc--; //消除前置0,方法与高精加略有不同 if(lc==1&&c[0]==0) flag=0; //相减为0的情况下不输出 - 号 if(flag) cout <<"-"; for (int i=lc;i>0;i--) { cout <<c[i]; } return 0; }
高精乘
/*========================================= 高精乘 核心算法:(列式计算中找出的规律) c[i+j-1] += a[i] * b[j]; c[i+j] += c[i+j-1]/10; c[i+j-1] %= 10 ; ==========================================*/ #include <iostream> #include <string> using namespace std; string s1,s2; int a[2008],b[2008],c[2008]; int main() { int la,lb,lc; cin >>s1 >>s2; la=s1.length(); lb=s2.length(); for (int i=0;i<la;i++) { a[la-i]=s1[i]-'0'; } for (int i=0;i<lb;i++) { b[lb-i]=s2[i]-'0'; } lc=la+lb; //c 数组的位数不会超过其和 for (int i=1;i<=la;i++) { for (int j=1;j<=lb;j++) { c[i+j-1] += a[i]*b[j]; //核心算法 c[i+j] += c[i+j-1]/10; //进位 c[i+j-1] %= 10; //留位 } } if (c[lc]==0&&lc>0) lc--; //消除前置零 for (int i=lc;i>0;i--) { cout <<c[i]; } return 0; }
三、总结&感想
学习的道路上艰辛却又看不见终点
好在大家走的路都是相似的
前人铺垫好的
我们感谢、使用、完善
例如,在减法中存在一个借位判断
在之后可能就会遇到别的相似判断
附上一道题,洛谷 P1009 阶层之和(写一起主要是懒得再写一篇了 ps:洛谷是一个网站啦)
/*=============================== 阶层之和很简单,一个循环就能搞定 但是只限于数目较小的时候 通过这一道题目来初步学习高精度算法 高精度就是说参与运算的数据和运算结果的范围 超出标准数据类型能表示的数据大小范围的运算 ================================*/ /*================================ 核心还是高精算法 关键还是把握整体思路 中间有一个判断 和借位判断类似 像是一个进位判断 ================================*/ #include<iostream> #include<bits/stdc++.h> using namespace std; int a[2000]; int b[2000]; int main() { a[1]=1; int n; cin >> n; for (int i=1;i<=n;i++) { for (int j=1;j<100;j++) //50个二位数一下累乘位数不会超过100 { a[j] *= i; //每一位先乘 } for (int j=1;j<100;j++) { if (a[j]>9) //进位判断 { a[j+1]+=(a[j]/10); a[j] %= 10; } } for (int k=1;k<100;k++) { b[k] += a[k]; //累加进入 b 数组 if (b[k]>9) { b[k+1] += (b[k]/10); b[k] %= 10; } } } int ws=100; //消除前置0(定义出一个位数) while(b[ws]==0) ws--; for (int i=ws;i>0;i--) { cout <<b[i]; } }