But my words, like silent raind|

MessageBoxA

园龄:4年10个月粉丝:5关注:0

一种不会丢失精度的分数表示法

众所周知,C++ 中就算是精度最高的浮点数 long double 也会存在可观的精度丢失的问题,那么我们该如何解决这个问题呢?高精度浮点数又显得过于夸张繁琐。

何不想个折中的法子?

于是,我们想到了一种办法,用 long long 分别表示分母和分子!

而我们在进行分数运算的时候,就可以模拟人工手算分数的办法来操作,比如说

ab+cd=ad+bcbd

之后再求gcd约分即可

而比较两个分数的方法也很简单

ab<cd  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;
}

本文作者:MessageBoxA

本文链接:https://www.cnblogs.com/SkyNet-PKN/p/17135648.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   MessageBoxA  阅读(47)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 evening Corn Wave
  2. 2 Группа крови Кино
  3. 3 The Sound Of Silence Simon & Garfunkel
  4. 4 dB doll YUE.STEVEN
Группа крови - Кино
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.