高精度
C++常用数据类型范围
#include<bits/stdc++.h>
using namespace std;
int main(){
//数据类型范围定义在limits.h中
printf("int\n字节数:%d\n最大值:%d\n最小值:%d\n",sizeof(int),INT_MAX,INT_MIN);
printf("unsigned\n字节数:%d\n最大值:%u\n最小值:%u\n",sizeof(unsigned),UINT_MAX,0);
printf("long long\n字节数:%lld\n最大值:%lld\n最小值:%lld\n",sizeof(long long ),LLONG_MAX,LLONG_MAX);
printf("unsigned long long\n字节数:%d\n最大值:%llu\n最小值:%llu\n",sizeof(unsigned long long),ULLONG_MAX,0);
//float.h
printf("float\n字节数:%d\n最大值:%f\n最小值:%f\n正最小:%e\n",sizeof(float),FLT_MAX,-FLT_MAX,FLT_MIN);
printf("double\n字节数:%d\n最大值:%e\n最小值:%e\n正最小:%e\n",sizeof(double),DBL_MAX,-DBL_MAX,DBL_MIN);
printf("long double\n字节数:%d\n最大值:%Le\n最小值:%Le\n正最小:%e\n",sizeof(long double),LDBL_MAX,-LDBL_MAX,LDBL_MIN);
//long double 完全输出用%Lf
int x=0xfffffff;
float y=0xfffffff;
//由于float尾数为(有效位)为23,而int为31所以相同的数字float会有误差,即float牺牲精度换取范围
printf("x:%d\ny:%f\n",x,y);
return 0;
}
运行结果
那么当我们需要存储或计算的数据过大时,就需要使用高精度了。
高精度(四位压缩)
对于数字100456789
存储的时候是这个样子
参考代码
#include<bits/stdc++.h>
// 高精度
// 四位压缩大法
using namespace std;
const int mlen=1e3,mod=1e4;
struct BD{
int p[mlen],len;
bool cha;//符号位 0为正,1为负
BD(){
memset(p,0,sizeof(p));
len=0;//存储时从第零位开始存储,方便乘法运算
cha=0;
}
BD(string &s){//字符串转高精
memset(p,0,sizeof(p));
len=0;
int beg=0;
if(s[0]=='-')cha=1,beg=1;
else cha=0;
for(int i=s.size()-1;i>=beg;i-=4){
int sum=0,base=1;
for(int j=0;j<4&&i-j>=beg;++j){
sum+=(s[i-j]-'0')*base;
base*=10;
}
p[len++]=sum;
}
}
void print(){//打印高精度的函数
if(cha)putchar('-');
if(len==0){putchar('0');return ;}
printf("%d",p[len-1]);//第一个四位数不需要前导零,单独打印
for(int i=len-2;i>=0;--i){
if(p[i]==0){
printf("0000");
continue;
}
for(int j=10;j*p[i]<mod;j*=10)printf("0");
printf("%d",p[i]);
}
}
BD operator+(const BD&a);//高精加高精
BD operator*(int a);//高精乘单精
BD operator*(const BD&a);//高精乘高精
bool operator<(const BD&a);//高精比大小
BD operator-(const BD&a);//高精减高精
};
//高精加高精
//符号位相同调这个
BD BD::operator+(const BD&a){
BD c;
c.len=max(len,a.len);
c.cha=a.cha;
int f=0;
for(int i=0;i<c.len;++i){
c.p[i]=p[i]+a.p[i]+f;
f=c.p[i]/mod;
c.p[i]%=mod;
}
if(f)c.p[c.len++]=f;
return c;
}
//高精乘单精
BD BD::operator*(int a){
BD c;
if(a<0){
a=-a;
c.cha=cha^1;
}
else c.cha=cha;
if(a==0)return c;
c.len=len;
int f=0;
for(int i=0;i<len;++i){
c.p[i]=p[i]*a+f;
f=c.p[i]/mod;
c.p[i]%=mod;
}
while(f){
c.p[c.len++]=f%mod;
f/=mod;
}
return c;
}
//高精比大小
bool BD::operator<(const BD&a){
if(len<a.len)return true;
else if(a.len<len)return false;
for(int i=len-1;i>=0;--i){
if(p[i]<a.p[i])return true;
else if(a.p[i]<p[i])return false;
}
return false;
}
//高精减高精
int flag;//帮助判断符号位
BD BD::operator-(const BD&a){//调用前先比较大小
BD c;
c.cha=cha^flag;
c.len=len;
int f=0;//标记是否借位
for(int i=0;i<len;++i){
if(p[i]+f<a.p[i]){
c.p[i]=p[i]+mod+f-a.p[i];
f=-1;
}
else {
f=0;
c.p[i]=p[i]-a.p[i];
}
}
while(c.len>0&&c.p[c.len-1]==0){
c.len--;
}
return c;
}
//高精乘高精
//n位数乘n位数最多得到2n位数
BD BD::operator*(const BD&a){
BD c;
c.cha=cha^a.cha;
for(int i=0;i<len;++i){
for(int j=0;j<a.len;++j){
c.p[i+j]+=p[i]*a.p[j];
c.p[i+j+1]+=c.p[i+j]/mod;
c.p[i+j]%=mod;//即刻进位,防止超出int范围
}
}
//删除前导零
c.len=a.len+len;
while(c.len>0&&c.p[c.len-1]==0)c.len--;
return c;
}
int main(){
string s1;
string s2;
cin>>s1>>s2;
BD a(s1),b(s2);
printf("s1+s2=");
if(a.cha==b.cha)(a+b).print();
else{
if(a<b)flag=0,(b-a).print();
else flag=0,(a-b).print();
}
putchar('\n');
printf("s1-s2=");
if(a.cha!=b.cha){
(b+a).print();
}
else{//此时符号位相同,用flag判断是否要改变符号即可
if(a<b)flag=1,(b-a).print();
else flag=0,(a-b).print();
}
putchar('\n');
printf("s1*s2=");
(a*b).print();
putchar('\n');
return 0;
}
思路不难,但是有很多细节要注意,符号,乘法偏移量,前导零\(\cdots\)
运行结果