有理數 (Rational Number)

C++ 實習測試: 有理數 (Rational Number) 類別製作

數學上,有理數 (rational number) 是一個整數 a 和一個非零整數 b 的比值,例如 3/8,又稱作分數。所有有理數的集合表示為 Q。 有理數的小數部分有限或為循環,不是有理數的實數稱為無理數 (irrational),有理數是可屬的 (countable)。

  • 一個有理數的表示法可以化簡 (reduce), 使得分子 a 和分母 b 互質
  • 兩個有理數可以執行 加法 乘法 的運算
  • 兩個有理數可以 比較是否相等
下面是一個實作 有理數C 程序化程式
#include <cassert>
#include <iostream>
using std::cin;
using std::cout;
using std::ostream;
using std::istream;
#include <iomanip>
using std::endl;
#include <cstdlib>
using std::abs;


struct Rational
{
    int _num;
    int _denom;
};

void add(Rational *lhs, Rational rhs);
void mult(Rational *lhs, Rational rhs);
bool equal(Rational lhs, Rational rhs);
void reduce(Rational *number);
int gcd(int a, int b);
void print(const char message[], Rational r);


int main()
{
    Rational a;
    Rational b = {1,2};
    Rational bad = {1,0};
    Rational c = {10,15};
    Rational verify1 = {7,5}, verify2 = {7,10};

    a._num = 27;
    a._denom = 30;
    print("a=", a);
    print("b=", b);

    print("bad=", bad);
    print("c=", c);
    reduce(&c);
    print("化簡後 c=", c);

    add(&a, b);
    print("a+b=", a);
    assert(equal(a,verify1));
    mult(&a, b);
    print("(a+b)*b=", a);
    assert(equal(a,verify2));

    return 0;
}


void print(const char message[], Rational r)
{
    cout << message << r._num << "/" << r._denom << endl;
}


void reduce(Rational *r)
{
    assert(r->_denom != 0);
    int divisor, num = abs(r->_num), denom = abs(r->_denom);
    if (num >= denom)
        divisor = gcd(num, denom);
    else
        divisor = gcd(denom, num);
    r->_num /= divisor;
    r->_denom /= divisor;
}


void add(Rational *lhs, Rational rhs)
{
    Rational temp;    
    int divisor;
    temp._num = lhs->_num * rhs._denom + rhs._num * lhs->_denom;
    temp._denom = lhs->_denom * rhs._denom;
    assert(temp._denom != 0);
    divisor = gcd(abs(temp._num), abs(temp._denom));
    temp._num /= divisor;
    temp._denom /= divisor;
    *lhs = temp;
}


void mult(Rational *lhs, Rational rhs)
{
    Rational temp;
    int divisor;
    temp._num = lhs->_num * rhs._num;
    temp._denom = lhs->_denom * rhs._denom;
    assert(temp._denom != 0);
    divisor = gcd(abs(temp._num), abs(temp._denom));
    temp._num /= divisor;
    temp._denom /= divisor;
    *lhs = temp;
}


bool equal(Rational lhs, Rational rhs)
{
reduce(&lhs);
reduce(&rhs);
return (lhs._num == rhs._num)&&(lhs._denom == rhs._denom);
} int gcd(int a, int b) // assume a>=b>=0 { if (b == 0) return a; return gcd(b, a%b); }

下面是一個實作 有理數C++ 物件化程式


/* Rational.h */

#pragma once

#include <iostream>
using std::ostream;
using std::istream;

class Rational
{
    friend ostream& operator<<(ostream&, const Rational &rhs);
    friend istream& operator>>(istream&, Rational &rhs);
public:
    Rational();
    Rational(int num, int denom);
    Rational(int whole);
    Rational add(const Rational &rhs);
    Rational mult(const Rational &rhs);
    bool equal(const Rational &rhs) const;
private:
    int gcd(int a, int b);
    int gcd0(int a, int b);
    int _num;
    int _denom;
};


/* Rational.cpp */

#include "rational.h"
#include <cassert>
#include <iostream>
using std::ostream;
using std::istream;
using std::abs;

ostream& operator<<(ostream& out, const Rational& rhs)
{
    if (rhs._denom == 0)
        out << "undefined" ;
    else
        out << rhs._num << "/" << rhs._denom;
    return out;
}


istream& operator>>(istream& in, Rational& rhs)
{
    in >> rhs._num >> rhs._denom;
    return in;
}


Rational::Rational():_num(0), _denom(1)
{
}


Rational::Rational(int num, int denom):_num(num), _denom(denom)
{
    assert(denom != 0);
    int divisor = gcd(abs(_num), abs(_denom));
    _num /= divisor;
    _denom /= divisor;
}


Rational::Rational(int whole):_num(whole), _denom(1)
{
}


Rational Rational::add(const Rational& rhs)
{
    Rational temp;
    int divisor;
    temp._num = _num * rhs._denom + rhs._num * _denom;
    temp._denom = _denom * rhs._denom;
    assert(temp._denom != 0);
    divisor = gcd(abs(temp._num), abs(temp._denom));
    temp._num /= divisor;
    temp._denom /= divisor;
    return temp;
}


Rational Rational::mult(const Rational& rhs)
{
    Rational temp;
    int divisor;
    temp._num = _num * rhs._num;
    temp._denom = _denom * rhs._denom;
    assert(temp._denom != 0);
    divisor = gcd(abs(temp._num), abs(temp._denom));
    temp._num /= divisor;
    temp._denom /= divisor;
    return temp;
}


bool Rational::equal(const Rational& rhs) const
{
    return (_num == rhs._num)&&(_denom == rhs._denom);
}


int Rational::gcd(int a, int b)
{
    if (a < b)
        return gcd0(b, a);
    if (b == 0) return a;
    return gcd0(b, a%b);
}


int Rational::gcd0(int a, int b)
{
    if (b == 0) return a;
    return gcd(b, a%b);
}


/* main.cpp */

#include "rational.h"
#include <cassert>
#include <iostream>
#include <iomanip>
using std::cin;
using std::cout;
using std::endl;

int main()
{
    Rational a;
    Rational b(1,2);
    // Rational bad(1,0); // assertion error
    Rational c(10);
    Rational bc(10, 20);
    
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;
    //cout << "bad=" << bad << endl;
    cout << "c=" << c << endl;
    
    cout << "Enter the rational number as num denom:";
    cin >> a;
    cout << "a=" << a << endl;
    cout << "a+b=" << a.add(b) << endl;
    cout << "a*b=" << a.mult(b) << endl;

    c.mult(b);
    assert(bc.equal(c));
    
    return 0;
}

C++ 物件導向程式設計課程 首頁

製作日期: 03/25/2015 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon