Rational.h
#ifndef RATIONAL_CLASS
#define RAIIONAL_CLASS
#include <iostream>
using namespace std;
class Rational {
private:
int numerator, denominator;
static int digits(double d);
static int gcd(int a, int b);
Rational normalize();
public:
Rational(int n = 0, int d = 1);
Rational(double d);
Rational(const Rational& r);
Rational& operator = (const Rational& rhs);
Rational operator + (const Rational& rhs) const ;
Rational operator – (const Rational& rhs) const ;
Rational operator * (const Rational& rhs) const ;
Rational operator / (const Rational& rhs) const ;
Rational& operator += (const Rational& rhs);
Rational& operator -= (const Rational& rhs);
Rational& operator *= (const Rational& rhs);
Rational& operator /= (const Rational& rhs);
friend Rational operator + (int n, const Rational& rhs);
friend Rational operator – (int n, const Rational& rhs);
friend Rational operator * (int n, const Rational& rhs);
friend Rational operator / (int n, const Rational& rhs);
friend int& operator += (int& n, const Rational& rhs);
friend int& operator -= (int& n, const Rational& rhs);
friend int& operator *= (int& n, const Rational& rhs);
friend int& operator /= (int& n, const Rational& rhs);
friend Rational operator + (double n, const Rational& rhs);
friend Rational operator – (double n, const Rational& rhs);
friend Rational operator * (double n, const Rational& rhs);
friend Rational operator / (double n, const Rational& rhs);
friend double& operator += (double& n, const Rational& rhs);
friend double& operator -= (double& n, const Rational& rhs);
friend double& operator *= (double& n, const Rational& rhs);
friend double& operator /= (double& n, const Rational& rhs);
bool operator > (const Rational& rhs) const;
bool operator == (const Rational& rhs) const;
bool operator >= (const Rational& rhs) const;
bool operator < (const Rational& rhs) const;
bool operator <= (const Rational& rhs) const;
bool operator != (const Rational& rhs) const;
friend bool operator > (int n, const Rational& rhs);
friend bool operator >= (int n, const Rational& rhs);
friend bool operator < (int n, const Rational& rhs);
friend bool operator <= (int n, const Rational& rhs);
friend bool operator == (int n, const Rational& rhs);
friend bool operator != (int n, const Rational& rhs);
friend bool operator > (double n, const Rational& rhs);
friend bool operator >= (double n, const Rational& rhs);
friend bool operator < (double n, const Rational& rhs);
friend bool operator <= (double n, const Rational& rhs);
friend bool operator == (double n, const Rational& rhs);
friend bool operator != (double n, const Rational& rhs);
Rational operator + () const;
Rational operator – () const;
Rational& operator ++ ();
Rational operator ++ (int);
Rational& operator — ();
Rational operator — (int);
operator int () const;
operator double () const;
friend ostream& operator << (ostream& os, const Rational& rhs) ;
friend istream& operator >> (istream& is, const Rational& rhs);
void Print() {
cout << this->normalize() << endl;
}
};
#endif
Rational.cpp
#include <iostream>
#include <cassert>
#include <cmath>
#include “Rational.h”
using namespace std;
int Rational::digits(double d) {
char buffer[64];
sprintf(buffer, “%g”, d);
int n = strlen(buffer);
int i = 0;
while (buffer[i] != “”\0″” && buffer[i] != “”.””)
++i;
if(i == n)
return 0;
return n – i – 1;
}
int Rational::gcd(int a, int b) {
int r;
while(b != 0) {
r = a % b;
a = b;
b = r;
}
return a;
}
Rational Rational::normalize() {
int n = gcd(this->numerator, this->denominator);
assert(n != 0);
this->numerator /= n;
this->denominator /= n;
if(this->denominator < 0) {
this->numerator *= -1;
this->denominator *= -1;
}
return *this;
}
Rational::Rational(int n, int d) {
this->numerator = n;
this->denominator = (d == 0 ? 1 : d);
}
Rational::Rational(double d) {
int n = Rational::digits(d);
double e = pow(10.0, n);
this->numerator = int(d * e);
this->denominator = int(e);
this->normalize();
}
Rational::Rational(const Rational& r) {
this->numerator = r.numerator;
this->denominator = r.denominator;
}
Rational& Rational::operator = (const Rational& rhs) {
this->numerator = rhs.numerator;
this->denominator = rhs.denominator;
return *this;
}
Rational Rational::operator + (const Rational& rhs) const {
Rational r;
r.numerator = this->numerator * rhs.denominator +
this->denominator * rhs.numerator;
r.denominator = this->denominator * rhs.denominator;
return r.normalize();
}
Rational Rational::operator – (const Rational& rhs) const {
Rational r;
r.numerator = this->numerator * rhs.denominator –
this->denominator * rhs.numerator;
r.denominator = this->denominator * rhs.denominator;
return r.normalize();
}
Rational Rational::operator * (const Rational& rhs) const {
Rational r;
r.numerator = this->numerator * rhs.numerator;
r.denominator = this->denominator * rhs.denominator;
return r.normalize();
}
Rational Rational::operator / (const Rational& rhs) const {
assert(rhs.numerator != 0);
Rational r;
r.numerator = this->numerator * rhs.denominator;
r.denominator = this->denominator * rhs.numerator;
return r.normalize();
}
Rational& Rational::operator += (const Rational& rhs) {
return *this = *this + rhs;
}
Rational& Rational::operator -= (const Rational& rhs) {
return *this = *this – rhs;
}
Rational& Rational::operator *= (const Rational& rhs) {
return *this = *this * rhs;
}
Rational& Rational::operator /= (const Rational& rhs) {
return *this = *this / rhs;
}
Rational operator + (int n, const Rational& rhs) {
return Rational(n) + rhs;
}
Rational operator – (int n, const Rational& rhs) {
return Rational(n) – rhs;
}
Rational operator * (int n, const Rational& rhs) {
return Rational(n) * rhs;
}
Rational operator / (int n, const Rational& rhs) {
return Rational(n) / rhs;
}
int& operator += (int& n, const Rational& rhs) {
n = n * rhs.denominator + rhs.numerator;
return n /= rhs.denominator;
}
int& operator -= (int& n, const Rational& rhs) {
n = n * rhs.denominator – rhs.numerator;
return n /= rhs.denominator;
}
int& operator *= (int& n, const Rational& rhs) {
n = n * rhs.numerator;
return n /= rhs.denominator;
}
int& operator /= (int& n, const Rational& rhs) {
assert(rhs.numerator != 0);
n = n * rhs.denominator;
return n /= rhs.numerator;
}
Rational operator + (double n, const Rational& rhs) {
return Rational(n) + rhs;
}
Rational operator – (double n, const Rational& rhs) {
return Rational(n) – rhs;
}
Rational operator * (double n, const Rational& rhs) {
return Rational(n) * rhs;
}
Rational operator / (double n, const Rational& rhs) {
return Rational(n) / rhs;
}
double& operator += (double& n, const Rational& rhs) {
return n += (double)rhs.numerator / rhs.denominator;
}
double& operator -= (double& n, const Rational& rhs) {
return n -= (double)rhs.numerator / rhs.denominator;
}
double& operator *= (double& n, const Rational& rhs) {
return n *= (double)rhs.numerator / rhs.denominator;
}
double& operator /= (double& n, const Rational& rhs) {
return n /= (double)rhs.numerator / rhs.denominator;
}
bool Rational::operator < (const Rational& rhs) const {
return (*this – rhs).numerator < 0;
}
bool Rational::operator == (const Rational& rhs) const {
return (*this – rhs).numerator == 0;
}
bool Rational::operator > (const Rational& rhs) const {
return rhs < *this;
}
bool Rational::operator >= (const Rational& rhs) const {
return !(*this < rhs);
}
bool Rational::operator <= (const Rational& rhs) const {
return !(*this > rhs);
}
bool Rational::operator != (const Rational& rhs) const {
return !(*this == rhs);
}
bool operator > (int n, const Rational& rhs) {
return Rational(n) > rhs;
}
bool operator >= (int n, const Rational& rhs) {
return Rational(n) >= rhs;
}
bool operator < (int n, const Rational& rhs) {
return Rational(n) < rhs;
}
bool operator <= (int n, const Rational& rhs) {
return Rational(n) <= rhs;
}
bool operator == (int n, const Rational& rhs) {
return Rational(n) == rhs;
}
bool operator != (int n, const Rational& rhs) {
return Rational(n) != rhs;
}
bool operator > (double n, const Rational& rhs) {
return n > (double)rhs.numerator / rhs.denominator;
}
bool operator >= (double n, const Rational& rhs) {
return n >= (double)rhs.numerator / rhs.denominator;
}
bool operator < (double n, const Rational& rhs) {
return n < (double)rhs.numerator / rhs.denominator;
}
bool operator <= (double n, const Rational& rhs) {
return n <= (double)rhs.numerator / rhs.denominator;
}
bool operator == (double n, const Rational& rhs) {
return n == (double)rhs.numerator / rhs.denominator;
}
bool operator != (double n, const Rational& rhs) {
return n != (double)rhs.numerator / rhs.denominator;
}
Rational Rational::operator + () const {
return *this;
}
Rational Rational::operator – () const {
return Rational(- this->numerator, this->denominator);
}
Rational& Rational::operator ++ () {
this->numerator += this->denominator;
return *this;
}
Rational Rational::operator ++ (int) {
Rational temp(*this);
++(*this);
return temp;
}
Rational& Rational::operator — () {
this->numerator -= this->denominator;
return *this;
}
Rational Rational::operator — (int) {
Rational temp(*this);
–(*this);
return temp;
}
Rational::operator int () const {
return this->numerator / this->denominator;
}
Rational::operator double () const {
return (double)this->numerator / this->denominator;
}
ostream& operator << (ostream& os, const Rational& rhs) {
os << rhs.numerator << “/ ” << rhs.denominator;
return os;
}
istream& operator >> (istream& is, const Rational& rhs) {
char dump;
is >> rhs.numerator >> dump >> rhs.denominator;
return is;
}
#ifndef RATIONAL_CLASS
#define RAIIONAL_CLASS
#include <iostream>
using namespace std;
class Rational {
private:
int numerator, denominator;
static int digits(double d);
static int gcd(int a, int b);
Rational normalize();
public:
Rational(int n = 0, int d = 1);
Rational(double d);
Rational(const Rational& r);
Rational& operator = (const Rational& rhs);
Rational operator + (const Rational& rhs) const ;
Rational operator – (const Rational& rhs) const ;
Rational operator * (const Rational& rhs) const ;
Rational operator / (const Rational& rhs) const ;
Rational& operator += (const Rational& rhs);
Rational& operator -= (const Rational& rhs);
Rational& operator *= (const Rational& rhs);
Rational& operator /= (const Rational& rhs);
friend Rational operator + (int n, const Rational& rhs);
friend Rational operator – (int n, const Rational& rhs);
friend Rational operator * (int n, const Rational& rhs);
friend Rational operator / (int n, const Rational& rhs);
friend int& operator += (int& n, const Rational& rhs);
friend int& operator -= (int& n, const Rational& rhs);
friend int& operator *= (int& n, const Rational& rhs);
friend int& operator /= (int& n, const Rational& rhs);
friend Rational operator + (double n, const Rational& rhs);
friend Rational operator – (double n, const Rational& rhs);
friend Rational operator * (double n, const Rational& rhs);
friend Rational operator / (double n, const Rational& rhs);
friend double& operator += (double& n, const Rational& rhs);
friend double& operator -= (double& n, const Rational& rhs);
friend double& operator *= (double& n, const Rational& rhs);
friend double& operator /= (double& n, const Rational& rhs);
bool operator > (const Rational& rhs) const;
bool operator == (const Rational& rhs) const;
bool operator >= (const Rational& rhs) const;
bool operator < (const Rational& rhs) const;
bool operator <= (const Rational& rhs) const;
bool operator != (const Rational& rhs) const;
friend bool operator > (int n, const Rational& rhs);
friend bool operator >= (int n, const Rational& rhs);
friend bool operator < (int n, const Rational& rhs);
friend bool operator <= (int n, const Rational& rhs);
friend bool operator == (int n, const Rational& rhs);
friend bool operator != (int n, const Rational& rhs);
friend bool operator > (double n, const Rational& rhs);
friend bool operator >= (double n, const Rational& rhs);
friend bool operator < (double n, const Rational& rhs);
friend bool operator <= (double n, const Rational& rhs);
friend bool operator == (double n, const Rational& rhs);
friend bool operator != (double n, const Rational& rhs);
Rational operator + () const;
Rational operator – () const;
Rational& operator ++ ();
Rational operator ++ (int);
Rational& operator — ();
Rational operator — (int);
operator int () const;
operator double () const;
friend ostream& operator << (ostream& os, const Rational& rhs) ;
friend istream& operator >> (istream& is, const Rational& rhs);
void Print() {
cout << this->normalize() << endl;
}
};
#endif
Rational.cpp
#include <iostream>
#include <cassert>
#include <cmath>
#include “Rational.h”
using namespace std;
int Rational::digits(double d) {
char buffer[64];
sprintf(buffer, “%g”, d);
int n = strlen(buffer);
int i = 0;
while (buffer[i] != “”\0″” && buffer[i] != “”.””)
++i;
if(i == n)
return 0;
return n – i – 1;
}
int Rational::gcd(int a, int b) {
int r;
while(b != 0) {
r = a % b;
a = b;
b = r;
}
return a;
}
Rational Rational::normalize() {
int n = gcd(this->numerator, this->denominator);
assert(n != 0);
this->numerator /= n;
this->denominator /= n;
if(this->denominator < 0) {
this->numerator *= -1;
this->denominator *= -1;
}
return *this;
}
Rational::Rational(int n, int d) {
this->numerator = n;
this->denominator = (d == 0 ? 1 : d);
}
Rational::Rational(double d) {
int n = Rational::digits(d);
double e = pow(10.0, n);
this->numerator = int(d * e);
this->denominator = int(e);
this->normalize();
}
Rational::Rational(const Rational& r) {
this->numerator = r.numerator;
this->denominator = r.denominator;
}
Rational& Rational::operator = (const Rational& rhs) {
this->numerator = rhs.numerator;
this->denominator = rhs.denominator;
return *this;
}
Rational Rational::operator + (const Rational& rhs) const {
Rational r;
r.numerator = this->numerator * rhs.denominator +
this->denominator * rhs.numerator;
r.denominator = this->denominator * rhs.denominator;
return r.normalize();
}
Rational Rational::operator – (const Rational& rhs) const {
Rational r;
r.numerator = this->numerator * rhs.denominator –
this->denominator * rhs.numerator;
r.denominator = this->denominator * rhs.denominator;
return r.normalize();
}
Rational Rational::operator * (const Rational& rhs) const {
Rational r;
r.numerator = this->numerator * rhs.numerator;
r.denominator = this->denominator * rhs.denominator;
return r.normalize();
}
Rational Rational::operator / (const Rational& rhs) const {
assert(rhs.numerator != 0);
Rational r;
r.numerator = this->numerator * rhs.denominator;
r.denominator = this->denominator * rhs.numerator;
return r.normalize();
}
Rational& Rational::operator += (const Rational& rhs) {
return *this = *this + rhs;
}
Rational& Rational::operator -= (const Rational& rhs) {
return *this = *this – rhs;
}
Rational& Rational::operator *= (const Rational& rhs) {
return *this = *this * rhs;
}
Rational& Rational::operator /= (const Rational& rhs) {
return *this = *this / rhs;
}
Rational operator + (int n, const Rational& rhs) {
return Rational(n) + rhs;
}
Rational operator – (int n, const Rational& rhs) {
return Rational(n) – rhs;
}
Rational operator * (int n, const Rational& rhs) {
return Rational(n) * rhs;
}
Rational operator / (int n, const Rational& rhs) {
return Rational(n) / rhs;
}
int& operator += (int& n, const Rational& rhs) {
n = n * rhs.denominator + rhs.numerator;
return n /= rhs.denominator;
}
int& operator -= (int& n, const Rational& rhs) {
n = n * rhs.denominator – rhs.numerator;
return n /= rhs.denominator;
}
int& operator *= (int& n, const Rational& rhs) {
n = n * rhs.numerator;
return n /= rhs.denominator;
}
int& operator /= (int& n, const Rational& rhs) {
assert(rhs.numerator != 0);
n = n * rhs.denominator;
return n /= rhs.numerator;
}
Rational operator + (double n, const Rational& rhs) {
return Rational(n) + rhs;
}
Rational operator – (double n, const Rational& rhs) {
return Rational(n) – rhs;
}
Rational operator * (double n, const Rational& rhs) {
return Rational(n) * rhs;
}
Rational operator / (double n, const Rational& rhs) {
return Rational(n) / rhs;
}
double& operator += (double& n, const Rational& rhs) {
return n += (double)rhs.numerator / rhs.denominator;
}
double& operator -= (double& n, const Rational& rhs) {
return n -= (double)rhs.numerator / rhs.denominator;
}
double& operator *= (double& n, const Rational& rhs) {
return n *= (double)rhs.numerator / rhs.denominator;
}
double& operator /= (double& n, const Rational& rhs) {
return n /= (double)rhs.numerator / rhs.denominator;
}
bool Rational::operator < (const Rational& rhs) const {
return (*this – rhs).numerator < 0;
}
bool Rational::operator == (const Rational& rhs) const {
return (*this – rhs).numerator == 0;
}
bool Rational::operator > (const Rational& rhs) const {
return rhs < *this;
}
bool Rational::operator >= (const Rational& rhs) const {
return !(*this < rhs);
}
bool Rational::operator <= (const Rational& rhs) const {
return !(*this > rhs);
}
bool Rational::operator != (const Rational& rhs) const {
return !(*this == rhs);
}
bool operator > (int n, const Rational& rhs) {
return Rational(n) > rhs;
}
bool operator >= (int n, const Rational& rhs) {
return Rational(n) >= rhs;
}
bool operator < (int n, const Rational& rhs) {
return Rational(n) < rhs;
}
bool operator <= (int n, const Rational& rhs) {
return Rational(n) <= rhs;
}
bool operator == (int n, const Rational& rhs) {
return Rational(n) == rhs;
}
bool operator != (int n, const Rational& rhs) {
return Rational(n) != rhs;
}
bool operator > (double n, const Rational& rhs) {
return n > (double)rhs.numerator / rhs.denominator;
}
bool operator >= (double n, const Rational& rhs) {
return n >= (double)rhs.numerator / rhs.denominator;
}
bool operator < (double n, const Rational& rhs) {
return n < (double)rhs.numerator / rhs.denominator;
}
bool operator <= (double n, const Rational& rhs) {
return n <= (double)rhs.numerator / rhs.denominator;
}
bool operator == (double n, const Rational& rhs) {
return n == (double)rhs.numerator / rhs.denominator;
}
bool operator != (double n, const Rational& rhs) {
return n != (double)rhs.numerator / rhs.denominator;
}
Rational Rational::operator + () const {
return *this;
}
Rational Rational::operator – () const {
return Rational(- this->numerator, this->denominator);
}
Rational& Rational::operator ++ () {
this->numerator += this->denominator;
return *this;
}
Rational Rational::operator ++ (int) {
Rational temp(*this);
++(*this);
return temp;
}
Rational& Rational::operator — () {
this->numerator -= this->denominator;
return *this;
}
Rational Rational::operator — (int) {
Rational temp(*this);
–(*this);
return temp;
}
Rational::operator int () const {
return this->numerator / this->denominator;
}
Rational::operator double () const {
return (double)this->numerator / this->denominator;
}
ostream& operator << (ostream& os, const Rational& rhs) {
os << rhs.numerator << “/ ” << rhs.denominator;
return os;
}
istream& operator >> (istream& is, const Rational& rhs) {
char dump;
is >> rhs.numerator >> dump >> rhs.denominator;
return is;
}
解决方案:5分
+-*/一般不提供 const 签名函数
原因是 双目运算符一般实现为 friend
分数,一般也没有必要重载++,–
一般 operator +=,-=,*=,/= 实现为 成员函数
基于一致性原则 operator +,-,*,/
往往直接调用 operator +=,-=,*=,/= 实现,避免出现两份相同的代码,以及不一致。
单目 +- 实现为 成员函数,+直接返回 *this; – 返回新的对象(分子取相反数即可)
另外,调试的时候,一个函数一个函数调试更简单,更快,更容易发现问题。
原因是 双目运算符一般实现为 friend
分数,一般也没有必要重载++,–
一般 operator +=,-=,*=,/= 实现为 成员函数
基于一致性原则 operator +,-,*,/
往往直接调用 operator +=,-=,*=,/= 实现,避免出现两份相同的代码,以及不一致。
单目 +- 实现为 成员函数,+直接返回 *this; – 返回新的对象(分子取相反数即可)
另外,调试的时候,一个函数一个函数调试更简单,更快,更容易发现问题。
解决方案:2分
另外,你想要什么样子的结果,程序输出是什么,编译有没有警告信息,都贴出来
解决方案:5分
一行写一句。
不要在同一个表达式里同时修改并使用一个值,尽管可能不构成未定义行为,但是可读性会很差。
不要在同一个表达式里同时修改并使用一个值,尽管可能不构成未定义行为,但是可读性会很差。
解决方案:3分
你可以参考ffmpeg中AVRational的实现代码,不过是用c语言实现的
解决方案:5分
这几个函数很够呛,不带这么玩的
用operator + 实现operator += 是错误的做法,
原因是结果和操作数 ,是相同的数据,
结果是 最后的结果不对,原因是计算是分步骤计算的,
中间的步骤,没有使用原始数据,而是使用了被修改一半的脏数据。
同理,-=,*=,/=,也是错误的。
用operator + 实现operator += 是错误的做法,
原因是结果和操作数 ,是相同的数据,
结果是 最后的结果不对,原因是计算是分步骤计算的,
中间的步骤,没有使用原始数据,而是使用了被修改一半的脏数据。
同理,-=,*=,/=,也是错误的。