当前位置 博文首页 > 一位初中编程爱好者的博客:C++分数类(大整数类版)

    一位初中编程爱好者的博客:C++分数类(大整数类版)

    作者:[db:作者] 时间:2021-08-29 22:30

    1.简介

    该博文是C++分数类的姊妹篇。那篇博文中type对应的类型是long long,虽然范围很大,但还是可能溢出。我最近做了一个大整数类,理论上可以保存无限大的整数,于是,我把这两个类结合了起来,并添加了一些新功能,就成了这个版本的分数类。
    注:由于大整数类不存在溢出现象,但运算速度慢,尤其是约分(求最大公约数),需要进行多次取模运算,所以在前一个版本的分数类中一些牺牲时间来防止溢出的代码被删除了,简化了代码的同时提高了效率(如乘法原来需要4次约分、3次复制,现在只需1次约分,同样的程序运行时间由125毫秒降至78毫秒)。

    2.代码

    改进后的分数类代码如下:(测试代码见第一篇博客)

    //CFraction.h
    #pragma once
    #include<stdexcept>
    #include"CBigInt.h"
    class CFraction
    {
    private:
    	typedef CBigInt type;
    	type numerator;//分子
    	type denominator;//分母
    	static type GCD(type x, type y);
    	static type LCM(const type& x, const type& y);
    public:
    	CFraction();
    	CFraction(type, type);
    	CFraction(const CFraction&);
    	CFraction(long double);
    	const type& GetNumerator()const;
    	const type& GetDenominator()const;
    	long double GetFractionalValue()const;
    	void SetNumerator(const type&);
    	void SetDenominator(const type&);
    	void Assign(const type&, const type&);
    	void Assign(long double);
    	void Assign(const CFraction&);
    	void ReductionOfTheFraction();//约分
    	void ReductionOfTheFractionToACommonDenominator(CFraction&);//通分
    	CFraction Reciprocal()const;//倒数
    	CFraction operator=(const CFraction&);
    	CFraction operator=(long double);
    	/*
    	friend bool operator>(CFraction, CFraction);
    	friend bool operator<(CFraction, CFraction);
    	friend bool operator>=(CFraction, CFraction);
    	friend bool operator<=(CFraction, CFraction);
    	*/
    	friend std::strong_ordering operator<=>(CFraction, CFraction);
    	//使用C++20中的三路比较运算符
    	friend bool operator==(const CFraction& f1, const CFraction& f2);
    	friend bool operator!=(const CFraction& f1, const CFraction& f2);
    	friend CFraction operator+(CFraction, CFraction);
    	friend CFraction operator-(CFraction, CFraction);
    	friend CFraction operator*(CFraction, CFraction);
    	friend CFraction operator/(CFraction, CFraction);
    	CFraction& operator+=(const CFraction&);
    	CFraction& operator-=(const CFraction&);
    	CFraction& operator*=(const CFraction&);
    	CFraction& operator/=(const CFraction&);
    	CFraction operator-()const;
    	bool IsIrreducibleFraction()const;//是否为最简分数
    	bool CanItBeAFiniteDecimal()const;//能否化成有限小数
    	type Floor()const;
    	type Ceil()const;
    };
    
    
    
    //CFraction.cpp
    #include "CFraction.h"
    CFraction::type CFraction::GCD(type x, type y)
    {
    	type t;
    	while (y != 0)
    	{
    		t = x % y;
    		x = y;
    		y = t;
    	}
    	return x;
    }
    
    CFraction::type CFraction::LCM(const type& x, const type& y)
    {
    	return x * y / GCD(x, y);
    }
    
    CFraction::CFraction()
    {
    	numerator = 1;
    	denominator = 1;
    }
    
    CFraction::CFraction(type n, type d = 1)
    {
    	Assign(n, d);
    }
    
    CFraction::CFraction(const CFraction& fraction)
    {
    	Assign(fraction);
    }
    
    CFraction::CFraction(long double d)
    {
    	Assign(d);
    }
    
    const CFraction::type& CFraction::GetNumerator()const
    {
    	return numerator;
    }
    
    const CFraction::type& CFraction::GetDenominator()const
    {
    	return denominator;
    }
    
    long double CFraction::GetFractionalValue() const
    {
    	return (numerator.ToLongDouble() / denominator.ToLongDouble());
    }
    
    void CFraction::SetNumerator(const type& n)
    {
    	numerator = n;
    }
    
    void CFraction::SetDenominator(const type& d)
    {
    	if (d == 0)
    		throw std::invalid_argument("分母为0!");
    	denominator = d;
    }
    
    void CFraction::Assign(const type& n, const type& d)
    {
    	if (d == 0)
    		throw std::invalid_argument("分母为0!");
    	numerator = n;
    	denominator = d;
    }
    
    void CFraction::Assign(long double d)
    {
    	if (d == 0)
    		throw std::invalid_argument("参数为0!");
    	type i = 1;
    	while (d - floorl(d) > 1e-15)
    	{
    		d *= 10;
    		i *= 10;
    	}
    	std::string str = std::to_string(d);
    	this->numerator = 
    		str.substr(0, str.find('.'));
    	this->denominator = i;
    	this->ReductionOfTheFraction();
    }
    
    void CFraction::Assign(const CFraction& fraction)
    {
    	this->numerator = fraction.numerator;
    	this->denominator = fraction.denominator;
    }
    
    void CFraction::ReductionOfTheFraction()
    {
    	const type i = GCD(numerator, denominator);
    	numerator /= i;
    	denominator /= i;
    }
    
    void CFraction::ReductionOfTheFractionToACommonDenominator(CFraction& fraction)
    {
    	this->ReductionOfTheFraction();
    	fraction.ReductionOfTheFraction();
    	const type lcm = LCM(this->denominator, fraction.denominator);
    	this->numerator *= (lcm / this->denominator);//分母乘几,分子也乘几
    	fraction.numerator *= (lcm / fraction.denominator);
    	this->denominator = lcm;//分母等于最小公倍数
    	fraction.denominator = lcm;
    }
    
    CFraction CFraction::operator=(const CFraction& fraction)
    {
    	Assign(