使用C++语言自己实现了一个分数类。
支持分数加减乘除四则运算,输入输出操作,分数大小比较等基本功能。支持用模板自定义表示分子和分母的整数类型。
语法严谨,缩进适当,注释简洁。
/** 有理数模板类实现文件 Rational.h
** @obertys V5.0 2023/07/21
**
** 有理数实现为整数与整数之比,如1\2、-9\4等
** 支持有理数加减乘除四则运算,输入输出操作,有理数大小比较等基本功能
** 注意在输入输出中,分数线表示为反斜杠'\\'
**
** 模板类型integer必须有符号(支持负数)且支持基本运算,不建议将浮点数作为模板类型参数
**/
#include<iostream>
/*友元模板函数前置声明*/
template<typename integer> class Rational;
template<typename integer> std::istream& operator>>(std::istream& input,Rational<integer>& fraction);
template<typename integer> std::ostream& operator<<(std::ostream& output,const Rational<integer>& fraction);
template<typename integer> std::string& operator>>(std::string& input,Rational<integer>& fraction);
template<typename integer> std::string& operator<<(std::string& output,const Rational<integer>& fraction);
template<typename integer> bool operator==(const Rational<integer>& fractionA,const Rational<integer>& fractionB);
template<typename integer> bool operator<(const Rational<integer>& fractionA,const Rational<integer>& fractionB);
template<typename integer> bool operator>(const Rational<integer>& fractionA,const Rational<integer>& fractionB);
template<typename integer> Rational<integer> operator+(const Rational<integer>& fractionA,const Rational<integer>& fractionB);
template<typename integer> Rational<integer> operator-(const Rational<integer>& fractionA,const Rational<integer>& fractionB);
template<typename integer> Rational<integer> operator*(const Rational<integer>& fractionA,const Rational<integer>& fractionB);
template<typename integer> Rational<integer> operator/(const Rational<integer>& fractionA,const Rational<integer>& fractionB);
/*有理数模板类定义*/
template<typename integer>
class Rational
{
public:
/*异常类型*/
struct DivideByZero {}; //除以0异常类
/*流输入输出运算符*/
/*可输入一个整数或一个整数除以另一个整数的形式,输入的正号或负号应总是在第一个整数之前*/
/*输入示例:-1 0 25 8\3 -9\51*/
/*输出为一个整数,或一个整数除以另一个整数的形式*/
/*输出示例:-1 0 25 8\3 -9\51*/
friend std::istream& operator>> <>(std::istream& input,Rational& fraction);
friend std::ostream& operator<< <>(std::ostream& output,const Rational& fraction);
/*字符串输入输出运算符(流输入输出的字符串版本)*/
friend std::string& operator>> <>(std::string& input,Rational& fraction);
friend std::string& operator<< <>(std::string& output,const Rational& fraction);
/*大小比较运算符*/
friend bool operator== <>(const Rational& fractionA,const Rational& fractionB);
friend bool operator==(const Rational& fractionA,const integer& fractionB)
{
return fractionA==Rational(fractionB);
}
friend bool operator==(const integer& fractionA,const Rational& fractionB)
{
return Rational(fractionA)==fractionB;
}
friend bool operator!=(const Rational& fractionA,const Rational& fractionB)
{
return !(fractionA==fractionB);
}
friend bool operator!=(const integer& fractionA,const Rational& fractionB)
{
return !(fractionA==fractionB);
}
friend bool operator!=(const Rational& fractionA,const integer& fractionB)
{
return !(fractionA==fractionB);
}
friend bool operator< <>(const Rational& fractionA,const Rational& fractionB);
friend bool operator<(const integer& fractionA,const Rational& fractionB)
{
return Rational(fractionA)<fractionB;
}
friend bool operator<(const Rational& fractionA,const integer& fractionB)
{
return fractionA<Rational(fractionB);
}
friend bool operator<=(const Rational& fractionA,const Rational& fractionB)
{
return !(fractionA>fractionB);
}
friend bool operator<=(const integer& fractionA,const Rational& fractionB)
{
return !(fractionA>fractionB);
}
friend bool operator<=(const Rational& fractionA,const integer& fractionB)
{
return !(fractionA>fractionB);
}
friend bool operator> <>(const Rational& fractionA,const Rational& fractionB);
friend bool operator>(const integer& fractionA,const Rational& fractionB)
{
return Rational(fractionA)>fractionB;
}
friend bool operator>(const Rational& fractionA,const integer& fractionB)
{
return fractionA>Rational(fractionB);
}
friend bool operator>=(const Rational& fractionA,const Rational& fractionB)
{
return !(fractionA<fractionB);
}
friend bool operator>=(const integer& fractionA,const Rational& fractionB)
{
return !(fractionA<fractionB);
}
friend bool operator>=(const Rational& fractionA,const integer& fractionB)
{
return !(fractionA<fractionB);
}
/*一元运算符+-*/
friend Rational operator+(const Rational& fraction)
{
return fraction;
}
friend Rational operator-(const Rational& fraction)
{
return Rational(-fraction.numerator,fraction.denominator);
}
/*二元运算符+,-,*,/*/
friend Rational operator+ <>(const Rational& fractionA,const Rational& fractionB);
friend Rational operator- <>(const Rational& fractionA,const Rational& fractionB);
friend Rational operator* <>(const Rational& fractionA,const Rational& fractionB);
friend Rational operator/ <>(const Rational& fractionA,const Rational& fractionB);
friend Rational operator+(const integer& fractionA,const Rational& fractionB)
{
return Rational(fractionA)+fractionB;
}
friend Rational operator-(const integer& fractionA,const Rational& fractionB)
{
return Rational(fractionA)-fractionB;
}
friend Rational operator*(const integer& fractionA,const Rational& fractionB)
{
return Rational(fractionA)*fractionB;
}
friend Rational operator/(const integer& fractionA,const Rational& fractionB)
{
return Rational(fractionA)/fractionB;
}
friend Rational operator+(const Rational& fractionA,const integer& fractionB)
{
return fractionA+Rational(fractionB);
}
friend Rational operator-(const Rational& fractionA,const integer& fractionB)
{
return fractionA-Rational(fractionB);
}
friend Rational operator*(const Rational& fractionA,const integer& fractionB)
{
return fractionA*Rational(fractionB);
}
friend Rational operator/(const Rational& fractionA,const integer& fractionB)
{
return fractionA/Rational(fractionB);
}
/*构造函数*/
Rational(void):numerator(0),denominator(1) {} //有理数0
Rational(integer Numberator,integer Denominator); //有理数Numberator/Denominator
/*转换函数*/
Rational(integer wholeNumber):numerator(wholeNumber),denominator(1) {} //有理数wholeNumber
template<typename T> T toDecimal(void) const //返回分数的小数形式
{
return static_cast<T>(numerator)/static_cast<T>(denominator);
}
/*取值/赋值函数*/
integer Numerator(void) const //返回分子
{
return numerator;
}
integer Denominator(void) const //返回分母
{
return denominator;
}
void Numerator(integer Numerator_); //设置分子
void Denominator(integer Denominator_); //设置分母
/*一元运算符+=,-=,*=,/=*/
void operator+=(const Rational& fraction)
{
*this=*this+fraction;
return;
}
void operator-=(const Rational& fraction)
{
*this=*this-fraction;
return;
}
void operator*=(const Rational& fraction)
{
*this=*this*fraction;
return;
}
void operator/=(const Rational& fraction)
{
if(fraction==0)
throw DivideByZero();
*this=*this/fraction;
return;
}
void operator+=(const integer& fraction)
{
*this=*this+fraction;
return;
}
void operator-=(const integer& fraction)
{
*this=*this-fraction;
return;
}
void operator*=(const integer& fraction)
{
*this=*this*fraction;
return;
}
void operator/=(const integer& fraction)
{
if(fraction==0)
throw DivideByZero();
*this=*this/fraction;
return;
}
private:
/*数据变量*/
integer numerator; //分子
integer denominator; //分母
/*辅助成员函数*/
void reduction(void); //约分
};
/*辅助函数*/
template<typename integer> static integer gcd_lcm(register integer x,register integer y,char op) //op为'G'返回x,y最大公约数,为'L'返回x,y最小公倍数
{
//x的符号,y的符号,gcd的符号,lcm的符号:正正正正,负负负负,正负正负,负正负正
integer temp=x*y,z;
while(y) //辗转反除
{
z=x%y;
x=y;
y=z;
}
switch(op)
{
case 'G':
return x;
case 'L':
return temp/x;
default:
return 0;
}
}
template<typename integer> inline char sing(integer a) //返回a的符号
{
return a<0?'-':'+';
}
template<typename integer> inline integer abs(integer a) //返回a的绝对值
{
return a<0?-a:a;
}
/*有理数模板类成员函数、友元函数实现*/
template<typename integer> Rational<integer>::Rational(integer Numberator,integer Denominator):numerator(Numberator),denominator(Denominator) //有理数Numberator/Denominator
{
reduction();
}
template<typename integer> void Rational<integer>::reduction(void) //约分
{
integer num_gcd=gcd_lcm(numerator,denominator,'G'); //求最大公约数
numerator/=num_gcd,denominator/=num_gcd; //约分赋值
if(denominator<0)
numerator=-numerator,denominator=-denominator;
else if(denominator==0)
throw DivideByZero();
}
template<typename integer> void Rational<integer>::Numerator(integer Numerator_) //设置分子
{
numerator=Numerator_;
return;
}
template<typename integer> void Rational<integer>::Denominator(integer Denominator_) //设置分母
{
if(Denominator_<0)
numerator=-numerator,denominator=-Denominator_;
else
denominator=Denominator_;
return;
}
template<typename integer> std::istream& operator>>(std::istream& input,Rational<integer>& fraction) //流输入
{
input>>fraction.numerator;
if(input.peek()=='\\')
{
input.ignore(1);
input>>fraction.denominator;
fraction.reduction();
}
else
fraction.denominator=1;
return input;
}
template<typename integer> std::ostream& operator<<(std::ostream& output,const Rational<integer>& fraction) //流输出
{
output<<fraction.numerator;
if(fraction.denominator!=1)
output<<'\\'<<fraction.denominator;
return output;
}
template<typename integer> std::string& operator>>(std::string& input,Rational<integer>& fraction) //字符串输入
{
char* ptr;
const char* input_str=input.c_str();
fraction.numerator=strtoll(input_str,&ptr,10);
if(*ptr=='\\')
{
fraction.denominator=strtoll(ptr+1,&ptr,10);
fraction.reduction();
}
else
fraction.denominator=1;
input.erase(0,ptr-input_str); //擦除字符串中提取的分数
return input;
}
template<typename integer> std::string& operator<<(std::string& output,const Rational<integer>& fraction) //字符串输出
{
output+=to_string(fraction.numerator); //后缀分子至字符串
if(fraction.denominator!=1)
output+='\\'+to_string(fraction.denominator);
return output;
}
template<typename integer> bool operator==(const Rational<integer>& fractionA,const Rational<integer>& fractionB)
{
return fractionA.numerator*fractionB.denominator==fractionA.denominator*fractionB.numerator;
}
template<typename integer> bool operator<(const Rational<integer>& fractionA,const Rational<integer>& fractionB)
{
return fractionA.numerator*fractionB.denominator<fractionA.denominator*fractionB.numerator;
}
template<typename integer> bool operator>(const Rational<integer>& fractionA,const Rational<integer>& fractionB)
{
return fractionA.numerator*fractionB.denominator>fractionA.denominator*fractionB.numerator;
}
template<typename integer> Rational<integer> operator+(const Rational<integer>& fractionA,const Rational<integer>& fractionB)
{
Rational<integer> ret; //A+B
ret.denominator=gcd_lcm(fractionA.denominator,fractionB.denominator,'L'); //分母为最小公倍数
ret.numerator=fractionA.numerator*(ret.denominator/fractionA.denominator)+fractionB.numerator*(ret.denominator/fractionB.denominator); //分子为A,B分子通分后的和
ret.reduction(); //约分
return ret;
}
template<typename integer> Rational<integer> operator-(const Rational<integer>& fractionA,const Rational<integer>& fractionB)
{
Rational<integer> ret; //A-B
ret.denominator=gcd_lcm(fractionA.denominator,fractionB.denominator,'L'); //分母为最小公倍数
ret.numerator=fractionA.numerator*(ret.denominator/fractionA.denominator)-fractionB.numerator*(ret.denominator/fractionB.denominator); //分子为A,B分子通分后的差
ret.reduction(); //约分
return ret;
}
template<typename integer> Rational<integer> operator*(const Rational<integer>& fractionA,const Rational<integer>& fractionB)
{
Rational<integer> ret;
Rational<integer> A_temp(fractionA.numerator,fractionB.denominator);
Rational<integer> B_temp(fractionB.numerator,fractionA.denominator);
ret.numerator=A_temp.numerator*B_temp.numerator; //分子相乘得分子
ret.denominator=A_temp.denominator*B_temp.denominator; //分母相乘得分母
return ret;
}
template<typename integer> Rational<integer> operator/(const Rational<integer>& fractionA,const Rational<integer>& fractionB)
{
Rational<integer> B_temp(fractionB.denominator,fractionB.numerator); //A/B=A*(1/B);
if(B_temp.denominator==0) //除数为0
throw typename Rational<integer>::DivideByZero();
return fractionA*B_temp;
}