C++ 无符号高精度计算合集
前言
在遇到一些数据比较大的计算,int
和long long
都撑不住的时候,我i们就需要用到高精算法(例如著名的a+b problem
)
这次就我就贴上高精度计算的完整代码(因为时间问题,暂时不支持负数和小数)
实现内容
高精度比较(无符号)
- 高精度大于
用字符串储存a、b两数,像判断位数,位数大即成立,位数小即不成立;在从高位到低位逐个判断,一旦该位不相等,大于即成立,小于即不成立
bool gjd_greater(string a,string b) { //大于
if(a.size()>b.size())return true;
else if(a.size()<b.size())return false;
else {
for(int i=0; i<a.size(); i++) {
int a2=a[i]-'0',b2=b[i]-'0',c=a2-b2;
if(c>0)return true;
else if(c<0)return false;
}
}
return false;
}
- 高精度小于
用字符串储存a、b两数,像判断位数,位数大即不成立,位数小即成立;在从高位到低位逐个判断,一旦该位不相等,大于即不成立,小于即成立
bool gjd_less(string a,string b) { //小于
if(a.size()<b.size())return true;
else if(a.size()>b.size())return false;
else {
for(int i=0; i<a.size(); i++) {
int a2=a[i]-'0',b2=b[i]-'0',c=a2-b2;
if(c<0)return true;
else if(c>0)return false;
}
}
return false;
}
- 高精度等于
用字符串储存a、b两数,利用字符串特性,a==b即成立
bool gjd_equal(string a,string b) { //等于
return a==b;
}
- 高精度大于等于
用字符串储存a、b两数,不小于即成立
bool gjd_gore(string a,string b) { //大于等于
return !gjd_less(a,b);
}
- 高精度小于等于
用字符串储存a、b两数,不大于即成立
bool gjd_lore(string a,string b) { //小于等于
return !gjd_greater(a,b);
}
高精度计算(无符号)
- 高精度加法
用字符串储存a、b两数,模拟加法运算,从低位到高位加,超过9的要进位。
string gjd_add(string a,string b) { //加法
string c;
int x=0;
while(a.size()<b.size())a='0'+a;
while(b.size()<a.size())b='0'+b;
for(int i=a.size()-1; i>=0; i--) {
int a2=a[i]-'0',b2=b[i]-'0',c2=a2+b2+x;
c=(char)(c2%10+'0')+c;
x=c2/10;
}
if(x)c=(char)(x+'0')+c;
return c;
}
- 高精度减法
用字符串储存a、b两数,模拟减法运算,从低位到高位减,不够减的要向下一位借位
string gjd_minus(string a,string b) { //减法
string c;
int x=0;
while(a.size()<b.size())a='0'+a;
while(b.size()<a.size())b='0'+b;
for(int i=a.size()-1; i>=0; i--) {
int a2=a[i]-'0',b2=b[i]-'0',c2=a2-b2-x;
if(c2>=0)c=(char)(c2+'0')+c,x=0;
else c=(char)((c2+10)+'0')+c,x=1;
}
while(c[0]=='0')c.erase(0,1);
if(c.size()==0)c+='0';
return c;
}
- 高精度乘法(高精乘高精)
用字符串储存a、b两数,模拟乘法运算,
- 从b的低位到高位,将该位与a数相乘,转换成高精乘低精
- 循环将该位与a数的个位相乘,从低位到高位,得到该位与a数相乘的结果
- 将结果后补0:该位是b数的个位不补0,是十位补1个0,是百位补2个0……
- 将补0后的结果存入数组
- 将数组内所有数进行高精加,得到最终结果
string gjd_times(string a,string b) { //乘法
string c[10005],s;
int as=a.size(),bs=b.size(),x;
for(int i=bs-1; i>=0; i--) {
x=0;
for(int j=as-1; j>=0; j--) {
int a2=a[j]-'0',b2=b[i]-'0',c2=a2*b2+x;
c[i]=(char)(c2%10+'0')+c[i];
x=c2/10;
}
if(x)c[i]=(char)(x+'0')+c[i];
for(int j=1; j<bs-i; j++)c[i]+='0';
}
for(int i=0; i<bs; i++)s=gjd_add(s,c[i]);
while(s[0]=='0')s.erase(0,1);
if(s.size()==0)s+='0';
return s;
}
- 高精度除法(高精除以高精)
用字符串储存a、b两数,模拟除法运算,从1-10试商,将商存入数组,不够除时商0
string gjd_division(string a,string b) { //除法
string c;
int x=0;
int la=a.size(),lb=b.size();
string cs=a.substr(0,lb);
a.erase(0,lb);
while(gjd_gore(cs,b))cs=gjd_minus(cs,b),x++;
c+=(char)(x+'0');
while(a.size()) {
x=0;
cs+=a[0],a.erase(0,1);
while(cs[0]=='0')cs.erase(0,1);
if(cs.size()==0)cs+='0';
while(gjd_gore(cs,b))cs=gjd_minus(cs,b),x++;
c+=(char)(x+'0');
}
while(c[0]=='0')c.erase(0,1);
if(c.size()==0)c+='0';
return c;
}
- 高精度阶乘(低精度参数)
用整型int储存a数,循环高精乘
string gjd_jc(int n) { //阶乘
string a="1";
for(int i=2; i<=n; i++)a=gjd_times(a,to_string(i));
return a;
}
- 高精度阶乘之和(低精度参数)
用整型int储存a数,循环高精阶乘,记忆优化
string gjd_jcsum(int n) { //阶乘之和
string s="0",ls="1";
for(int i=1; i<=n; i++) {
ls=gjd_times(ls,to_string(i));
s=gjd_add(s,ls);
}
return s;
}
- 高精度乘方(高精度的低精度次幂)
用字符串储存a底数,用整型int储存多少次方,循环高精乘
string gjd_pow(string a,int p) { //乘方
string s="1";
for(int i=1; i<=p; i++)s=gjd_times(s,a);
return s;
}
- 高精度取余(高精mod高精)
用字符串储存a、b两数,通过取余公式进行高精运算:
a−b∗(int)(a/b) a-b*(int)(a/b) a−b∗(int)(a/b)
string gjd_mod(string a,string b) { //取余
return gjd_minus(a,gjd_times(gjd_division(a,b),b));
}
源码展示
为了方便调用,我们先把函数定义到上面
#include <bits/stdc++.h>
using namespace std;
//高精度计算
string gjd_add(string a,string b); //加法
string gjd_minus(string a,string b); //减法
string gjd_times(string a,string b); //乘法
string gjd_division(string a,string b); //除法
string gjd_mod(string a,string b); //取余
string gjd_jc(int n); //阶乘
string gjd_jcsum(int n); //阶乘之和
string gjd_pow(string a,int p); //乘方
bool gjd_greater(string a,string b); //大于
bool gjd_less(string a,string b); //小于
bool gjd_equal(string a,string b); //等于
bool gjd_gore(string a,string b); //大于等于
bool gjd_lore(string a,string b); //小于等于
string gjd_add(string a,string b) { //加法
string c;
int x=0;
while(a.size()<b.size())a='0'+a;
while(b.size()<a.size())b='0'+b;
for(int i=a.size()-1; i>=0; i--) {
int a2=a[i]-'0',b2=b[i]-'0',c2=a2+b2+x;
c=(char)(c2%10+'0')+c;
x=c2/10;
}
if(x)c=(char)(x+'0')+c;
return c;
}
string gjd_minus(string a,string b) { //减法
string c;
int x=0;
while(a.size()<b.size())a='0'+a;
while(b.size()<a.size())b='0'+b;
for(int i=a.size()-1; i>=0; i--) {
int a2=a[i]-'0',b2=b[i]-'0',c2=a2-b2-x;
if(c2>=0)c=(char)(c2+'0')+c,x=0;
else c=(char)((c2+10)+'0')+c,x=1;
}
while(c[0]=='0')c.erase(0,1);
if(c.size()==0)c+='0';
return c;
}
string gjd_times(string a,string b) { //乘法
string c[10005],s;
int as=a.size(),bs=b.size(),x;
for(int i=bs-1; i>=0; i--) {
x=0;
for(int j=as-1; j>=0; j--) {
int a2=a[j]-'0',b2=b[i]-'0',c2=a2*b2+x;
c[i]=(char)(c2%10+'0')+c[i];
x=c2/10;
}
if(x)c[i]=(char)(x+'0')+c[i];
for(int j=1; j<bs-i; j++)c[i]+='0';
}
for(int i=0; i<bs; i++)s=gjd_add(s,c[i]);
while(s[0]=='0')s.erase(0,1);
if(s.size()==0)s+='0';
return s;
}
string gjd_division(string a,string b) { //除法
string c;
int x=0;
int la=a.size(),lb=b.size();
string cs=a.substr(0,lb);
a.erase(0,lb);
while(gjd_gore(cs,b))cs=gjd_minus(cs,b),x++;
c+=(char)(x+'0');
while(a.size()) {
x=0;
cs+=a[0],a.erase(0,1);
while(cs[0]=='0')cs.erase(0,1);
if(cs.size()==0)cs+='0';
while(gjd_gore(cs,b))cs=gjd_minus(cs,b),x++;
c+=(char)(x+'0');
}
while(c[0]=='0')c.erase(0,1);
if(c.size()==0)c+='0';
return c;
}
string gjd_mod(string a,string b) { //取余
return gjd_minus(a,gjd_times(gjd_division(a,b),b));
}
string gjd_jc(int n) { //阶乘
string a="1";
for(int i=2; i<=n; i++)a=gjd_times(a,to_string(i));
return a;
}
string gjd_jcsum(int n) { //阶乘之和
string s="0",ls="1";
for(int i=1; i<=n; i++) {
ls=gjd_times(ls,to_string(i));
s=gjd_add(s,ls);
}
return s;
}
string gjd_pow(string a,int p) { //乘方
string s="1";
for(int i=1; i<=p; i++)s=gjd_times(s,a);
return s;
}
bool gjd_greater(string a,string b) { //大于
if(a.size()>b.size())return true;
else if(a.size()<b.size())return false;
else {
for(int i=0; i<a.size(); i++) {
int a2=a[i]-'0',b2=b[i]-'0',c=a2-b2;
if(c>0)return true;
else if(c<0)return false;
}
}
return false;
}
bool gjd_less(string a,string b) { //小于
if(a.size()<b.size())return true;
else if(a.size()>b.size())return false;
else {
for(int i=0; i<a.size(); i++) {
int a2=a[i]-'0',b2=b[i]-'0',c=a2-b2;
if(c<0)return true;
else if(c>0)return false;
}
}
return false;
}
bool gjd_gore(string a,string b) { //大于等于
return !gjd_less(a,b);
}
bool gjd_lore(string a,string b) { //小于等于
return !gjd_greater(a,b);
}
bool gjd_equal(string a,string b) { //等于
return a==b;
}
int sti(string a) { //string转int
int ans=0;
int n=a.size();
for(int i=0; i<n; i++) {
ans=ans*10+(a[i]-48);
}
return ans;
}
int main() {
string a,b;
int n;
cout<<"输入a,b(a>b,a!=0,b!=0):"<<endl;
cin>>a>>b;
n=sti(gjd_mod(b,"1000"));
cout<<"a+b="<<gjd_add(a,b)<<endl; //加法
cout<<"a-b="<<gjd_minus(a,b)<<endl; //减法
cout<<"a*b="<<gjd_times(a,b)<<endl; //乘法
cout<<"a/b="<<gjd_division(a,b)<<endl; //除法
cout<<"a%b="<<gjd_mod(a,b)<<endl; //取余
cout<<"a>b:"<<gjd_greater(a,b)<<endl; //大于
cout<<"a<b:"<<gjd_less(a,b)<<endl; //小于
cout<<"a==b:"<<gjd_equal(a,b)<<endl; //等于
cout<<"a>=b:"<<gjd_gore(a,b)<<endl; //大于等于
cout<<"a<=b:"<<gjd_lore(a,b)<<endl; //小于等于
cout<<"(b%1000)阶乘="<<gjd_jc(n)<<endl; //阶乘
cout<<"(b%1000)阶乘之和="<<gjd_jcsum(n)<<endl; //阶乘之和
cout<<"a^(b%1000)="<<gjd_pow(a,n)<<endl; //乘方
return 0;
}
效果演示
结束语
今天的学习就到这里了,你学会了吗