封装分数类

· · 个人记录

namespace std{
    template<class T=int>class frac{
    private:
        T Numerator=0,Denominator=1;
        T gcd(T a,T b){return (!b)?a:gcd(b,a%b);}
        void simplify(){
            if(Denominator==0)
                throw std::runtime_error("Denominator cannot be zero");
            if(Numerator==0){
                Denominator=1;
                return;
            }
            if(Denominator<0){
                Numerator=-Numerator;
                Denominator=-Denominator;
            }
            int common_divisor=gcd(std::abs(Numerator),Denominator);
            Numerator/=common_divisor;
            Denominator/=common_divisor;
        }
    public:
        frac(int num=0,int denom=1):Numerator(num),
        Denominator(denom){simplify();}
        T numerator(){return Numerator;}
        T denominator(){return Denominator;}
        frac operator+(const frac&other)const{
            T new_num=Numerator*other.denominator()+other.numerator()*Denominator;
            T new_denom=Denominator*other.denominator();
            return frac(new_num,new_denom);
        }
        frac operator-(const frac&other)const{
            T new_num=Numerator*other.denominator()-other.numerator()*Denominator;
            T new_denom=Denominator*other.denominator();
            return frac(new_num,new_denom);
        }
        frac operator*(const frac&other)const{
            int new_num=Numerator*other.numerator();
            int new_denom=Denominator*other.denominator();
            return frac(new_num,new_denom);
        }
        frac operator/(const frac&other)const{
            if(other.numerator()==0)
                throw std::runtime_error("Cannot divide by zero");
            int new_num=Numerator*other.denominator();
            int new_denom=Denominator*other.numerator();
            return frac(new_num,new_denom);
        }
        frac operator+=(const frac&other){return *this=*this+other;}
        frac operator-=(const frac&other){return *this=*this-other;}
        frac operator*=(const frac&other){return *this=*this*other;}
        frac operator/=(const frac&other){return *this=*this/other;}
        frac abs()const{return frac(std::abs(Numerator),Denominator);}
        frac operator-()const{return frac(-Numerator,Denominator);}
        bool operator==(const frac&other)const{return Numerator==other.numerator()&&Denominator==other.denominator();}
        bool operator!=(const frac&other)const{return !(*this==other);}
        bool operator< (const frac&other)const{return Numerator*other.denominator()<other.numerator()*Denominator;}
        bool operator> (const frac&other)const{return Numerator*other.denominator()>other.numerator()*Denominator;}
        bool operator<=(const frac&other)const{return !(*this>other);}
        bool operator>=(const frac&other)const{return !(*this<other);}
        double toDouble()const{return static_cast<double>(Numerator)/Denominator;}
        T toInt()const{return Numerator/Denominator;}
        friend ostream& operator<<(ostream&os,const frac&fraction){
            if(fraction.Denominator==1)os<<fraction.Numerator;
            else os<<fraction.Numerator<<"/"<<fraction.Denominator;
            return os;
        }
        friend istream& operator>>(istream&is,frac&fraction){
            char slash;
            is>>fraction.Numerator>>slash>>fraction.Denominator;
            if(slash!='/'){
                is.setstate(ios::failbit);
                fraction=frac();
            }
            else fraction.simplify();
            return is;
        }
    };
}

可搭配 __intinf 使用