Question:
Write a class for rational numbers. Each object in the class should have two integer values that define the rational number: the numerator and the denominator. For example, the fraction 5/6 would have a denominator of 5 and a numerator of 6. Include a constructor with two arguments that can be used to set the numerator and denominator (forbidding zero in the denominator). Provide default values of zero for the numerator and one for the denominator.
Overload the input and output operators. Numbers are to be read and written in the form 1/2, 32/15, 300/401, and so forth. Note that the numerator, the denominator, or both may contain a minus sign, so -1/2, 32/-15, and -300/-401 are possible.
Include a function to normalize the values stored so that, after normalization, the denominator is positive and as small as possible. For example, after normalization, 4/-8 would be represented the same as -1/2.
Overload the usual arithmetic operators to provide addition, subtraction, multiplication, and division of two rational numbers. Overload the usual comparison operations to allow comparison of two rational numbers.
Hints: Two rational numbers a/b and c/d are equal if a*d equals c*b. For positive rational numbers, a/b is less than c/d, provided a*d is less than c*b.
My answer:
rational.h
#pragma once
#include <iostream>
class rational_numbers{
public:
rational_numbers(){
numerator = 0;
denominator = 1;
};
rational_numbers(int a, int b);
friend std::ostream& operator <<(std::ostream& out, const rational_numbers& obj);
friend std::istream& operator >>(std::istream& in, rational_numbers& obj);
friend rational_numbers operator +(const rational_numbers& a, const rational_numbers& b);
friend rational_numbers operator -(const rational_numbers& a, const rational_numbers& b);
friend rational_numbers operator *(const rational_numbers& a, const rational_numbers& b);
friend rational_numbers operator /(const rational_numbers& a, const rational_numbers& b);
friend bool operator ==(const rational_numbers& a, const rational_numbers& b);
friend bool operator >(const rational_numbers& a, const rational_numbers& b);
friend bool operator <(const rational_numbers& a, const rational_numbers& b);
private:
void normalize();
int numerator, denominator;
};
rational.cpp
#include "rational.h"
#include <cassert>
#include <cmath>
rational_numbers::rational_numbers(int a, int b){
assert(b != 0);
numerator = a;
denominator = b;
this->normalize();
}
void rational_numbers::normalize(){
// 处理两种情况 1. 分子分母同时为负 2. 分子为正,分母为负
if((numerator < 0 && denominator < 0) || (numerator > 0 && denominator < 0)){
numerator = -numerator;
denominator = -denominator;
}
// 处理后的分母为正整数
int i = std::abs(denominator);
for(; i > 1; i--){
if(((int)std::abs(numerator) % i == 0) && ((int)std::abs(denominator) % i == 0)){
numerator /= i;
denominator /= i;
i = std::abs(denominator);
}
}
}
std::ostream& operator<<(std::ostream& out, const rational_numbers& obj){
if(obj.numerator != 0){
if(obj.denominator == 1){
out << obj.numerator;
} else {
out << obj.numerator << "/" << obj.denominator;
}
} else {
out << "0";
}
return out;
}
std::istream& operator >>(std::istream& in, rational_numbers& obj){
char i;
in >> obj.numerator >> i >> obj.denominator;
assert(obj.denominator != 0 && i == '/');
obj.normalize();
return in;
}
rational_numbers operator +(const rational_numbers& a, const rational_numbers& b){
int n = a.numerator*b.denominator + a.denominator*b.numerator;
int m = a.denominator * b.denominator;
return rational_numbers(n, m);
}
rational_numbers operator -(const rational_numbers& a, const rational_numbers& b){
int n = a.numerator*b.denominator - a.denominator*b.numerator;
int m = a.denominator * b.denominator;
return rational_numbers(n, m);
}
rational_numbers operator *(const rational_numbers& a, const rational_numbers& b){
int n = a.numerator * b.numerator;
int m = a.denominator * b.denominator;
return rational_numbers(n, m);
}
rational_numbers operator /(const rational_numbers& a, const rational_numbers& b){
int n = a.numerator * b.denominator;
int m = a.denominator * b.numerator;
return rational_numbers(n, m);
}
bool operator ==(const rational_numbers& a, const rational_numbers& b){
// 因为都是化简过的分数,直接比较
return ((a.numerator == b.numerator) && (a.denominator == b.denominator));
}
bool operator >(const rational_numbers& a, const rational_numbers& b){
rational_numbers c = a - b;
if(c.numerator <= 0){
return false;
} else {
return true;
}
}
bool operator <(const rational_numbers& a, const rational_numbers& b){
if(a == b){
return false;
} else {
return !(a > b);
}
}
main.cpp
#include <iostream>
#include "rational.h"
using namespace std;
int main(){
rational_numbers a(2, 3);
cout << "a = " << a << endl;
rational_numbers b;
cout << "please input b in the form of x/y" << endl;
cout << "b = ";
cin >> b;
cout << "b = " << b << endl;
rational_numbers c = a + b;
cout << "c = a + b = " << c << endl;
rational_numbers d = a - b;
cout << "d = a - b = " << d << endl;
rational_numbers e = a * b;
cout << "e = a * b = " << e << endl;
rational_numbers f = a / b;
cout << "f = a / b = " << f << endl;
if(a == b){
cout << "a is equal to b." << endl;
} else {
cout << "a and b are unequal." << endl;
}
if(a > b){
cout << "a > b is true." << endl;
} else {
cout << "a > b is false." << endl;
}
if(a < b){
cout << "a < b is true." << endl;
} else {
cout << "a < b is false." << endl;
}
return 0;
}
结果1:
a = 2/3
please input b in the form of x/y
b = 2/3
b = 2/3
c = a + b = 4/3
d = a - b = 0
e = a * b = 4/9
f = a / b = 1
a is equal to b.
a > b is false.
a < b is false.
结果2:
a = 2/3
please input b in the form of x/y
b = -6/9
b = -2/3
c = a + b = 0
d = a - b = 4/3
e = a * b = -4/9
f = a / b = -1
a and b are unequal.
a > b is true.
a < b is false.
结果3:
a = 2/3
please input b in the form of x/y
b = -10/-9
b = 10/9
c = a + b = 16/9
d = a - b = -4/9
e = a * b = 20/27
f = a / b = 3/5
a and b are unequal.
a > b is false.
a < b is true.
结果4:
a = 2/3
please input b in the form of x/y
b = 0/-9
b = 0
c = a + b = 2/3
d = a - b = 2/3
e = a * b = 0
a.out: /home/lw/ttttttest/ttt1/execrise/exe6/rational.cpp:6: rational_numbers::rational_numbers(int, int): Assertion `b != 0' failed.
已放弃 (核心已转储)
上例中的b为 0,但0不能作除数。
结果5:
a = 2/3
please input b in the form of x/y
b = 625/25
b = 25
c = a + b = 77/3
d = a - b = -73/3
e = a * b = 50/3
f = a / b = 2/75
a and b are unequal.
a > b is false.
a < b is true.
Reference:
整理自 Data Structures and Other Objects Using C++ ( Fourth Edition ) Michael Main, Walter Savitch. p124