Rational.h
#ifndef RATIONAL_H
#define RATIONAL_H
/** @file
* @brief rational和其操作符函数的完整定义
*/
/** @mainpage 有理数表示
* 合并所有的rantional的所有操作
* 该程序可以用于满足所有的运算符操作
* 源文件:@link Rational.h Rational.cpp @endlink
* @date 2013-11-10
* @author Alex Lin
* @version 1.0
*/
#include <cassert>
#include <cstdlib>
#include <istream>
#include <ostream>
#include <sstream>
/**
* @brief The Rational class
* 有理数操作
*/
class Rational
{
public:
Rational();
Rational(int num);
Rational(int num, int den);
Rational(double r);
Rational& operator = (Rational const& that);
float as_float();
double as_double();
long double as_long_double();
void assign(int num, int den);
void reduce();
friend Rational abs(Rational const & r);
friend Rational operator-(Rational const& r);
friend Rational operator+(Rational const& lhs, Rational const& rhs);
friend Rational operator-(Rational const& lhs, Rational const& rhs);
friend Rational operator*(Rational const& lhs, Rational const& rhs);
friend Rational operator/(Rational const& lhs, Rational const& rhs);
friend bool operator==(Rational const& a, Rational const& b);
friend bool operator!=(Rational const& a, Rational const& b);
friend bool operator<(Rational const& a, Rational const& b);
friend bool operator<=(Rational const& a, Rational const& b);
friend bool operator>(Rational const& a, Rational const& b);
friend bool operator>=(Rational const& a, Rational const& b);
friend std::istream& operator>>(std::istream& in, Rational& rat);
friend std::ostream& operator<<(std::ostream& out, Rational const& rat);
public:
static int gcd(int n, int m);
static int GCD( int n, int m );
static int LCM(int a, int b);
private:
int numerator; //< 分子
int denominator; //< 分母
};
#endif // RATIONAL_H
Rational.cpp
#include "Rational.h"
///使用欧几里德算法计算最大公约数
int Rational::gcd(int n, int m)
{
n = std::abs(n);
while ( m != 0){
int tmp(n%m);
n = m;
m = tmp;
}
return n;
}
///利用递归计算最大公约数
int Rational::GCD( int n, int m )
{
if ( n % m == 0 )
return m;
else
return GCD(m, n % m);
}
///求两个数的最小公倍数
int Rational::LCM(int a, int b)
{
int temp_lcm;
temp_lcm = a*b/GCD(a, b);//最小公倍数等于两数之积除以最大公约数
return temp_lcm;
}
Rational::Rational()
: numerator(0), denominator(1)
{/*空*/}
Rational::Rational(int num)
: numerator(num), denominator(1)
{/*空*/}
Rational::Rational(int num, int den)
: numerator(num), denominator(den)
{
reduce();
}
Rational::Rational(double r)
: numerator(static_cast<int>(r * 10000)), denominator(10000)
{
reduce();
}
Rational& Rational::operator =(Rational const& that)
{
this->numerator = that.numerator;
this->denominator = that.denominator;
return *this;
}
float Rational::as_float()
{
return static_cast<float>(numerator) / denominator;
}
double Rational::as_double()
{
return static_cast<double>(numerator) / denominator;
}
long double Rational::as_long_double()
{
return static_cast<long double>(numerator) / denominator;
}
///为分子、分母赋值并约分
void Rational::assign(int num, int den)
{
numerator = num;
denominator = den;
reduce();
}
///约分
void Rational::reduce()
{
assert(denominator!=0);
if(denominator < 0)
{
denominator = -denominator;
numerator = -numerator;
}
int div(gcd(numerator, denominator));
numerator = numerator / div;
denominator = denominator / div;
}
///有理数的绝对值
Rational abs(Rational const & r)
{
return (std::abs(r.numerator), r.denominator);
}
///将有理数取反的单目操作
Rational operator-(Rational const& r)
{
return Rational(-r.numerator, r.denominator);
}
///有理数相加
Rational operator+(Rational const& lhs, Rational const& rhs)
{
return Rational(lhs.numerator*rhs.denominator+rhs.numerator*lhs.denominator,
lhs.denominator*rhs.denominator);
}
///有理数想减
Rational operator-(Rational const& lhs, Rational const& rhs)
{
return Rational(lhs.numerator*rhs.denominator-rhs.numerator*lhs.denominator,
lhs.denominator*rhs.denominator);
}
///有理数相乘
Rational operator*(Rational const& lhs, Rational const& rhs)
{
return Rational(lhs.numerator*rhs.numerator, lhs.denominator*rhs.denominator);
}
///有理数相除
///检测除零错误
Rational operator/(Rational const& lhs, Rational const& rhs)
{
return Rational(lhs.numerator*rhs.denominator, lhs.numerator*rhs.numerator);
}
///比较两个有理数是否相等
bool operator==(Rational const& a, Rational const& b)
{
return a.numerator == b.numerator and a.denominator == b.denominator;
}
///比较两个有理数是否不等
bool operator!=(Rational const& a, Rational const& b)
{
return not (a == b);
}
///比较两个有理数是否小于关系
bool operator<(Rational const& a, Rational const& b)
{
return a.numerator*b.denominator < b.numerator*a.denominator;
}
///比较两个有理数是否是小于等于关系
bool operator<=(Rational const& a, Rational const& b)
{
return not (b < a);
}
///比较两个有理数是否是大于关系
bool operator>(Rational const& a, Rational const& b)
{
return b < a;
}
///比较两个有理数是否是大于等于关系
bool operator>=(Rational const& a, Rational const& b)
{
return not (b > a);
}
///读取有理数
///格式为@em 整数 @c / @em 整数
std::istream& operator >>(std::istream& in, Rational& rat)
{
int n(0), d(0);
char sep('\0');
if (not (in >> n >> sep))
// 读取分子或分隔符出错
in.setstate(in.failbit);
else if (sep !='/')
{
// 成功读取分子,但其后无/。
// 将读取的sep放回输入流,以备下次读取。
in.unget();
rat.assign(n, 1);
}
else if (in >> d)
// 成功读取分子、分隔符及分母
rat.assign(n, d);
else
in.setstate(in.failbit);
return in;
}
///写出有理数
///格式为@em 分子 @c / @em 分母
std::ostream& operator<<(std::ostream& out, Rational const& rat)
{
std::ostringstream tmp;
tmp << rat.numerator << '/' << rat.denominator;
out << tmp.str();
return out;
}