一种不会丢失精度的分数表示法
众所周知,C++ 中就算是精度最高的浮点数 long double 也会存在可观的精度丢失的问题,那么我们该如何解决这个问题呢?高精度浮点数又显得过于夸张繁琐。
何不想个折中的法子?
于是,我们想到了一种办法,用 long long 分别表示分母和分子!
而我们在进行分数运算的时候,就可以模拟人工手算分数的办法来操作,比如说
\[\frac{a}{b}+\frac{c}{d}=\frac{ad+bc}{bd}
\]
之后再求gcd约分即可
而比较两个分数的方法也很简单
\[\frac{a}{b}<\frac{c}{d}\ \Leftrightarrow\ ad<bc\ (a,b,c,d>0)
\]
坑点:
- 有负数时,比较大小时要分类讨论!
- 约分时gcd不要传负数进去,概率出玄学错误!
- 分母的负号一定要传给分子,不然 -114514/1919810 就会输出成 114514/-1919810 !
- 分母为1或者分子为0时,就不用输出分数线了!(这项看情况,有些题目强制分数形式输出)
struct Fraction{
LL up/*分子*/,down/*分母*/;
Fraction(){}
Fraction(LL a,LL b){
up=a;down=b;
reduction();
}
inline Fraction reduction(){
if(down<0){
up=-up;
down=-down;
}
LL div=__gcd(abs(up),abs(down));
up/=div;
down/=div;
return *this;
}
inline void flip(){//取倒数
swap(up,down);
}
inline void print(){
reduction();
if(down==1) cout<<up;
else cout<<up<<'/'<<down;
}
friend std::ostream & operator << (std::ostream &os,Fraction x){
x.reduction();
if(x.down==1) os<<x.up;
else os<<x.up<<'/'<<x.down;
return os;
}
};
inline Fraction operator + (const Fraction& x,const Fraction& y){
Fraction res;
res.up=x.up*y.down+x.down*y.up;
res.down=x.down*y.down;
res.reduction();
return res;
}
inline Fraction operator - (const Fraction& x,const Fraction& y){
Fraction res;
res.up=x.up*y.down-x.down*y.up;
res.down=x.down*y.down;
res.reduction();
return res;
}
inline Fraction operator * (const Fraction& x,const Fraction& y){
Fraction res;
res.up=x.up*y.up;
res.down=x.down*y.down;
res.reduction();
return res;
}
inline Fraction operator / (const Fraction& x,const Fraction& y){
Fraction res;
res.up=x.up*y.down;
res.down=x.down*y.up;
res.reduction();
return res;
}
inline bool operator < (const Fraction& x,const Fraction& y){
int tmp=(x.down<0)+(y.down<0);//判断负数个数
return tmp%2==0 ? (x.up*y.down<x.down*y.up) : (x.up*y.down>x.down*y.up);//压行,负数为奇数个变号,反之不变
}
inline bool operator <= (const Fraction& x,const Fraction& y){
int tmp=(x.down<0)+(y.down<0);
return tmp%2==0 ? (x.up*y.down<=x.down*y.up) : (x.up*y.down>=x.down*y.up);
}
inline bool operator > (const Fraction& x,const Fraction& y){
int tmp=(x.down<0)+(y.down<0);
return tmp%2==0 ? (x.up*y.down>x.down*y.up) : (x.up*y.down<x.down*y.up);
}
inline bool operator >= (const Fraction& x,const Fraction& y){
int tmp=(x.down<0)+(y.down<0);
return tmp%2==0 ? (x.up*y.down>=x.down*y.up) : (x.up*y.down<=x.down*y.up);
}
inline bool operator == (const Fraction& x,const Fraction& y){
return x.up*y.down==x.down*y.up;
}
inline bool operator != (const Fraction& x,const Fraction& y){
return x.up*y.down!=x.down*y.up;
}

浙公网安备 33010602011771号