C++分数类

1.简介

我用C++做了一个分数类,实现了加减乘除、比较大小、约分、通分等功能,其中比较大小用到了C++20的新特性之一——三路比较运算符。下面与大家分享一下代码(VS2019,C++20编译通过)。
注:此是旧版本的分数类,新版本代码点击查看

2.代码

代码不难理解,用到的都是一些数学原理。

//CFraction.h
#pragma once
#include<stdexcept>
class CFraction
{
    
    
private:
	typedef long long type;
	type numerator;//分子
	type denominator;//分母
	static type GCD(type x, type y);
	static type LCM(type x, type y);
public:
	CFraction();
	CFraction(type, type)
	CFraction(const CFraction&);
	CFraction(long double);
	type GetNumerator()const;
	type GetDenominator()const;
	long double GetFractionalValue()const;
	void SetNumerator(type);
	void SetDenominator(type);
	void Assign(type, type);
	void Assign(long double);
	void Assign(const CFraction&);
	void ReductionOfTheFraction();//约分
	void ReductionOfTheFractionToACommonDenominator(CFraction&);//通分
	CFraction Reciprocal();//倒数
	CFraction operator=(const CFraction&);
	CFraction operator=(long double);
	type Compare(CFraction)const;
	friend bool operator==(CFraction, CFraction);
	friend bool operator!=(CFraction, CFraction);
	/*
	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);
	//使用三路比较运算符代替4种比较运算符(需要C++20)
	friend CFraction operator+(CFraction, CFraction);
	friend CFraction operator-(CFraction, CFraction);
	friend CFraction operator*(CFraction, CFraction);
	friend CFraction operator/(CFraction, CFraction);
	friend CFraction operator+=(CFraction&, const CFraction&);
	friend CFraction operator-=(CFraction&, const CFraction&);
	friend CFraction operator*=(CFraction&, const CFraction&);
	friend CFraction operator/=(CFraction&, const CFraction&);
	bool IsIrreducibleFraction()const;//是否为最简分数
	bool CanItBeAFiniteDecimal()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(type x, 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);
}

CFraction::type CFraction::GetNumerator()const
{
    
    
	return numerator;
}

CFraction::type CFraction::GetDenominator()const
{
    
    
	return denominator;
}

long double CFraction::GetFractionalValue() const
{
    
    
	return (static_cast<long double>(numerator)/denominator);
}

void CFraction::SetNumerator(type n)
{
    
    
	numerator = n;
}

void CFraction::SetDenominator(type d)
{
    
    
	if (d == 0)
		throw std::invalid_argument("分母为0!");
	denominator = d;
}

void CFraction::Assign(type n, 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 - static_cast<long double>(static_cast<type>(d)) > 1e-15)
	{
    
    
		d *= 10;
		i *= 10;
	}
	this->numerator = static_cast<type>(d);
	this->denominator = i;
	this->ReductionOfTheFraction();
}

void CFraction::Assign(const CFraction& fraction)
{
    
    
	this->numerator = fraction.numerator;
	this->denominator = fraction.denominator;
}

void CFraction::ReductionOfTheFraction()
{
    
    
	type i = GCD(numerator, denominator);
	numerator /= i;
	denominator /= i;
}

void CFraction::ReductionOfTheFractionToACommonDenominator(CFraction& fraction)
{
    
    
	this->ReductionOfTheFraction();
	fraction.ReductionOfTheFraction();
	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(fraction);
	return *this;
}

CFraction CFraction::operator=(long double d)
{
    
    
	Assign(d);
	return *this;
}

CFraction CFraction::Reciprocal()
{
    
    
	return CFraction(this->denominator,this->numerator);
}

CFraction::type CFraction::Compare(CFraction fraction)const
{
    
    
	CFraction t(*this);
	t.ReductionOfTheFractionToACommonDenominator(fraction);
	return (t.numerator - fraction.numerator);
}
bool operator==(CFraction f1, CFraction f2)
{
    
    
	return (f1.Compare(f2) == 0);
}

bool operator!=(CFraction f1, CFraction f2)
{
    
    
	return (f1.Compare(f2) != 0);
}

/*
bool operator>(CFraction f1, CFraction f2)
{
	return (f1.Compare(f2) > 0);
}

bool operator<(CFraction f1, CFraction f2)
{
	return (f1.Compare(f2) < 0);
}

bool operator>=(CFraction f1, CFraction f2)
{
	return (f1.Compare(f2) >= 0);
}

bool operator<=(CFraction f1, CFraction f2)
{
	return (f1.Compare(f2) <= 0);
}
*/
std::strong_ordering operator<=>(CFraction f1, CFraction f2)
{
    
    
	f1.ReductionOfTheFractionToACommonDenominator(f2);
	return f1.numerator <=> f2.numerator;
}

CFraction operator+(CFraction f1, CFraction f2)
{
    
    
	f1.ReductionOfTheFractionToACommonDenominator(f2);
	f1.numerator += f2.numerator;
	f1.ReductionOfTheFraction();
	return f1;
}

CFraction operator-(CFraction f1, CFraction f2)
{
    
    
	f1.ReductionOfTheFractionToACommonDenominator(f2);
	f1.numerator -= f2.numerator;
	f1.ReductionOfTheFraction();
	return f1;
}

CFraction operator*(CFraction f1, CFraction f2)
{
    
    
	f1.ReductionOfTheFraction();
	f2.ReductionOfTheFraction();
	//先约分,防止溢出
	CFraction::type tmp=f1.numerator;
	f1.numerator = f2.numerator;
	f2.numerator = tmp;
	f1.ReductionOfTheFraction();
	f2.ReductionOfTheFraction();
	/*
	交换分子后再约分,防止溢出。例如,计算(10000000000/10000000001)*(10000000001/10000000000)时
	直接计算会溢出,交换分子后约分变成(1/1)*(1/1),不会溢出。
	*/
	f1.numerator *= f2.numerator;
	f1.denominator *= f2.denominator;
	return f1;//已是最简分数,无需约分
}

CFraction operator/(CFraction f1, CFraction f2)
{
    
    
	return operator*(f1, f2.Reciprocal());//除以一个数等于乘这个数的倒数
}

CFraction operator+=(CFraction& f1, const CFraction& f2)
{
    
    
	f1.Assign(f1 + f2);
	return f1;
}

CFraction operator-=(CFraction& f1, const CFraction& f2)
{
    
    
	f1.Assign(f1 - f2);
	return f1;
}

CFraction operator*=(CFraction& f1, const CFraction& f2)
{
    
    
	f1.Assign(f1 * f2);
	return f1;
}

CFraction operator/=(CFraction& f1, const CFraction& f2)
{
    
    
	f1.Assign(f1 / f2);
	return f1;
}

bool CFraction::IsIrreducibleFraction() const
{
    
    
	return (GCD(numerator, denominator) == 1);
}

bool CFraction::CanItBeAFiniteDecimal() const
{
    
    
	CFraction t(*this);
	t.ReductionOfTheFraction();
	while (1)//化成最简分数后判断分母是否只有2和5这两个因数
	{
    
    
		if (t.denominator % 2 == 0)
			t.denominator /= 2;
		else if (t.denominator % 5 == 0)
			t.denominator /= 5;
		else
		{
    
    
			if (t.denominator == 1)
				return true;
			return false;
		}
	}
}


//main.cpp
#include<iostream>
#include<iomanip>
#include"CFraction.h"
using namespace std;
void ShowFraction(CFraction f, string name, int i = 15)//i为输出精度
{
    
    
	cout << name << '=' << f.GetNumerator() << '/' << f.GetDenominator() << '\t'
		<< "分数值=" << setprecision(i) << f.GetFractionalValue() << endl;

}
int main()
{
    
    
	try {
    
    
		CFraction f1(15, 75);
		ShowFraction(f1, "分数1");
		f1.ReductionOfTheFraction();
		ShowFraction(f1, "约分后,分数1");
		ShowFraction(f1 / CFraction(1, 3), "(分数1)/(1/3)");
		if (f1 < 0.25)
			cout << "分数1<0.25" << endl;
		f1.Assign(10000000000, 10000000001);
		f1 *= CFraction(10000000001, 10000000000);
		ShowFraction(f1, "(10000000000/10000000001)*(10000000001/10000000000)");
		if (CFraction(165, 375).CanItBeAFiniteDecimal())
			cout << "165/375可以化成有限小数" << endl;
		else
			cout << "165/375不能化成有限小数" << endl;
		if (CFraction(7, 49).CanItBeAFiniteDecimal())
			cout << "7/49可以化成有限小数" << endl;
		else
			cout << "7/49不能化成有限小数" << endl;
	}
	catch (invalid_argument except) {
    
    
		cout << "出现参数无效异常!异常信息:" << except.what();
	}
	catch (...) {
    
    
		cout << "出现其它类型异常!" << endl;
	}
	system("pause");
	return 0;
}

程序运行结果如下:
运行结果

猜你喜欢

转载自blog.csdn.net/qq_54121864/article/details/112971641