1. 程式人生 > >C++實現分數類

C++實現分數類

在幾乎所有的語言中(至少我知道的語言都是這樣),浮點數都是有精度丟失的。

怎麼解決呢?

分數類就是解決辦法之一。


        分數類採用分數的形式,儲存了兩個整數之比,確保了精度。

        分數類,肯定是要有約分、通分等函式和加、減、乘、除運算子的。(當然,要先實現求最大公因數和最小公倍數函式)這些都是基本數學知識。

        程式碼如下:

#ifndef FRACTION_H
#define FRACTION_H
#include<iostream>
#include<cstdio>
using std::istream;
using std::ostream;
using std::getchar;
namespace math{
	template<typename T>
	T gcd(T x,T y){
		if(x<y){
			int temp=x;
			x=y,y=temp;
		}
		int z;
		while(y!=0){
			z=x%y,x=y,y=z;
		}
		return x;
	}
	template<typename T>
	T lcm(T x,T y){
		return x/gcd(x,y)*y;
	} 
}
template<typename T,typename Tvalue=double>  //T==int,long long,your big_int class ......
class fraction{
	private:
	T _up,_down;
	bool input_with_reduction,output_with_reduction,multi_optimize;
			//optimize指上界優化,即:以犧牲時間為代價換取不溢位 
	public:
	// constructors
	fraction(){
		_up=1,_down=1,input_with_reduction=output_with_reduction=1,multi_optimize=0;
	}
	fraction(T up,T down){
		_up=up,_down=down,input_with_reduction=output_with_reduction=1,multi_optimize=0;
		if(input_with_reduction) reduction();
	}
	fraction(bool optimize){
		_up=1,_down=1,input_with_reduction=output_with_reduction=1,multi_optimize=optimize;
	}
	fraction(T up,T down,bool optimize){
		_up=up,_down=down,input_with_reduction=output_with_reduction=1,multi_optimize=optimize;
		if(input_with_reduction) reduction();
	}
	fraction(bool input_reduct,bool output_reduct){
		_up=1,_down=1,input_with_reduction=input_reduct,output_with_reduction=output_reduct,
			multi_optimize=0;
	}
	fraction(T up,T down,bool input_reduct,bool output_reduct){
		_up=up,_down=down,input_with_reduction=input_reduct,output_with_reduction=output_reduct,
			multi_optimize=0;
		if(input_with_reduction) reduction();
	}
	fraction(bool input_reduct,bool output_reduct,bool optimize){
		_up=1,_down=1,input_with_reduction=input_reduct,output_with_reduction=output_reduct,
			multi_optimize=optimize;
	}
	fraction(T up,T down,bool input_reduct,bool output_reduct,bool optimize){
		_up=up,_down=down,input_with_reduction=input_reduct,output_with_reduction=output_reduct,
			multi_optimize=optimize;
		if(input_with_reduction) reduction();
	}
	// inputs
	friend istream& operator >> (istream& input,fraction<T>& the_frac){
		if(the_frac.input_with_reduction) the_frac.reduction();
		input>>the_frac._up;
		getchar();
		input>>the_frac._down;
		return input;
	}
	fraction<T> input_cin(bool with_reduction=1){
		if(with_reduction) reduction();
		using std::cin;
		cin>>_up;
		getchar();
		cin>>_down;
		return *this;
	}
	// outputs
	friend ostream& operator << (ostream& output,fraction<T> the_frac){
		if(the_frac.output_with_reduction) the_frac.reduction();
		output<<the_frac._up<<'/'<<the_frac._down;
		return output;
	}
	fraction<T> output_cout(bool with_reduction=1){
		if(with_reduction) reduction();
		using std::cout;
		cout<<_up<<'/'<<_down;
		return *this;
	}
	// basic_functions
	T up(){
		return _up;
	}
	T down(){
		return _down;
	}
	// (bool change)
	bool input_reduction(bool change_to){
		input_with_reduction=change_to;
		return change_to;
	}
	bool output_reduction(bool change_to){
		output_with_reduction=change_to;
		return change_to;
	}
	bool multi_optimize_change(bool change_to){
		multi_optimize=change_to;
		return change_to;
	}
	bool all_reduction(bool input_change_to,bool output_change_to){
		input_with_reduction=input_change_to,output_with_reduction=output_change_to;
		return input_change_to&&output_change_to;
	}
	bool all_bool_change(bool input_change_to,bool output_change_to,bool optimize_change_to){
		input_with_reduction=input_change_to,output_with_reduction=output_change_to,
			multi_optimize=optimize_change_to;
		return (input_change_to&&output_change_to)^optimize_change_to;
	}
	// (end of bool change)
	template<typename Tans=Tvalue>
	Tans value()const{
		return Tans(_up)/Tans(_down);
	}
	fraction<T> reduction(){  //約分 
		T gcd_result=math::gcd(_up,_down);
		_up/=gcd_result,_down/=gcd_result;
		return *this;
	}
	fraction<T> reciprocal(bool with_reduction=1)const{
		return fraction<T>(_down,_up,with_reduction,1);
	}
	template<typename T1,typename T2=T1>
	static void common(fraction<T1> &frac_x,fraction<T2> &frac_y){  //通分 
		T gcd_num=math::gcd(frac_x._down,frac_y._down);
		T1 x_multi_num=frac_y._down/gcd_num,y_multi_num=frac_x._down/gcd_num;
		frac_x._down*=x_multi_num,frac_x._up*=x_multi_num;
		frac_y._down*=y_multi_num,frac_y._up*=y_multi_num;
	}
	operator Tvalue()const{
		return Tvalue(_up)/Tvalue(_down);
	}
	// operator + , - , * , /
	// operator +
	fraction<T> operator + (T another_adder)const{
		fraction<T> frac_adder(another_adder*_down,_down,0,0);
		return fraction<T>(_up+frac_adder._up,_down,1,1);
	}
	fraction<T> operator + (fraction<T> another_adder)const{
		two_fracs<T> commoned=common_value(*this,another_adder);
		return fraction<T>(commoned.first._up+commoned.second._up,commoned.first._down,true,true);
	}
	friend fraction<T> operator + (T adder,fraction<T> frac_adder){
		fraction<T> frac_adder_eq1(adder*frac_adder._down,frac_adder._down,false,false);
		return fraction<T>(frac_adder._up+frac_adder_eq1._up,frac_adder._down,true,true);
	}
	//operator -
	fraction<T> operator - (fraction<T> another_adder)const{
		two_fracs<T> commoned=common_value(*this,another_adder);
		return fraction<T>(commoned.first._up-commoned.second._up,commoned.first._down,true,true);
	}
	friend fraction<T> operator - (T adder,fraction<T> frac_adder){
		fraction<T> frac_adder_eq1(adder*frac_adder._down,frac_adder._down,false,false);
		return fraction<T>(frac_adder_eq1._up-frac_adder._up,frac_adder._down,true,true);
	}
	//operator *
	fraction<T> operator * (T another_adder){
		T gcd_num;
		if((gcd_num=math::gcd(_down,another_adder))!=1)
			_down/=gcd_num,another_adder/=gcd_num;
		return fraction<T>(_up*another_adder,_down,false,false);
	}
	fraction<T> operator * (fraction<T> another_adder){
		if(multi_optimize){
			T gcd_num;
			if(math::gcd(_up,_down)!=1) reduction();
			if(math::gcd(another_adder._up,another_adder._down)!=1) another_adder.reduction();
			if((gcd_num=math::gcd(_up,another_adder._down))!=1) 
				_up/=gcd_num,another_adder._down/=gcd_num;
			if((gcd_num=math::gcd(_down,another_adder._up)!=1))
				_down/=gcd_num,another_adder._up/=gcd_num;
			return fraction<T>(_up*another_adder._up,_down*another_adder._down,false,false); 
		}
		else{
			return fraction<T>(_up*another_adder._up,_down*another_adder._down,true,true);
		}
	}
	friend fraction<T> operator * (T adder,fraction<T> frac_adder){
		T gcd_num;
		if((gcd_num=math::gcd(frac_adder._down,adder))!=1)
			frac_adder._down/=gcd_num,adder/=gcd_num;
		return fraction<T>(frac_adder._up*adder,frac_adder._down,false,false);
	}
	//operator /
	fraction<T> operator / (T divider){
		return operator * (fraction<T>(divider,1,multi_optimize));
	} 
	fraction<T> operator / (fraction<T> divider){
		return operator * (divider.reciprocal(!multi_optimize));
	}
	friend fraction<T> operator / (T dividend,fraction<T> divider){
		return operator * (dividend,divider.reciprocal(false));
	}
	// operator < , == , != , > , <= , >= 
	// operator <
	bool operator < (fraction<T> frac_arg)const{
		two_fracs<T> commoned=common_value(*this,frac_arg);
		return commoned.first._up<commoned.second._up;
	}
	bool operator < (T integer_arg)const{
		fraction<T> frac_arg_eqint(integer_arg*_down,_down,false,false);
		return _up<frac_arg_eqint._up;
	} 
	friend bool operator < (T integer_arg,fraction<T> frac_arg){
		fraction<T> frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
		return frac_arg._up<frac_arg_eqint._up;
	}
	// operator ==
	bool operator == (fraction<T> frac_arg)const{
		two_fracs<T> commoned=common_value(*this,frac_arg);
		return commoned.first._up==commoned.second._up;
	}
	bool operator == (T integer_arg)const{
		fraction<T> frac_arg_eqint(integer_arg*_down,_down,false,false);
		return _up==frac_arg_eqint._up;
	} 
	friend bool operator == (T integer_arg,fraction<T> frac_arg){
		fraction<T> frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
		return frac_arg._up==frac_arg_eqint._up;
	}
	// operator !=
	bool operator != (fraction<T> frac_arg)const{
		two_fracs<T> commoned=common_value(*this,frac_arg);
		return commoned.first._up!=commoned.second._up;
	}
	bool operator != (T integer_arg)const{
		fraction<T> frac_arg_eqint(integer_arg*_down,_down,false,false);
		return _up!=frac_arg_eqint._up;
	} 
	friend bool operator != (T integer_arg,fraction<T> frac_arg){
		fraction<T> frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
		return frac_arg._up!=frac_arg_eqint._up;
	}
	// operator >
	bool operator > (fraction<T> frac_arg)const{
		two_fracs<T> commoned=common_value(*this,frac_arg);
		return commoned.first._up>commoned.second._up;
	}
	bool operator > (T integer_arg)const{
		fraction<T> frac_arg_eqint(integer_arg*_down,_down,false,false);
		return _up>frac_arg_eqint._up;
	} 
	friend bool operator > (T integer_arg,fraction<T> frac_arg){
		fraction<T> frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
		return frac_arg._up>frac_arg_eqint._up;
	}
	// operator <=
	bool operator <= (fraction<T> frac_arg)const{
		two_fracs<T> commoned=common_value(*this,frac_arg);
		return commoned.first._up<=commoned.second._up;
	}
	bool operator <= (T integer_arg)const{
		fraction<T> frac_arg_eqint(integer_arg*_down,_down,false,false);
		return _up<=frac_arg_eqint._up;
	} 
	friend bool operator <= (T integer_arg,fraction<T> frac_arg){
		fraction<T> frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
		return frac_arg._up<=frac_arg_eqint._up;
	}
	// operator >=
	bool operator >= (fraction<T> frac_arg)const{
		two_fracs<T> commoned=common_value(*this,frac_arg);
		return commoned.first._up>=commoned.second._up;
	}
	bool operator >= (T integer_arg)const{
		fraction<T> frac_arg_eqint(integer_arg*_down,_down,false,false);
		return _up>=frac_arg_eqint._up;
	} 
	friend bool operator >= (T integer_arg,fraction<T> frac_arg){
		fraction<T> frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
		return frac_arg._up>=frac_arg_eqint._up;
	}
	// operator += , -= , *= , /=
	// operator +=
	fraction<T> operator += (fraction<T> add_num){
		return *this=*this+add_num;
	}
	fraction<T> operator += (T add_num){
		return *this=*this+add_num;
	}
	friend fraction<T> operator += (T add_num,fraction<T> add_frac){
		return add_frac=add_frac+add_num;
	}
	// operator -=
	fraction<T> operator -= (fraction<T> add_num){
		return *this=*this-add_num;
	}
	fraction<T> operator -= (T add_num){
		return *this=*this-add_num;
	}
	friend fraction<T> operator -= (T add_num,fraction<T> add_frac){
		return add_frac=add_frac-add_num;
	}
	// operator *=
	fraction<T> operator *= (fraction<T> add_num){
		return *this=*this*add_num;
	}
	fraction<T> operator *= (T add_num){
		return *this=*this*add_num;
	}
	friend fraction<T> operator *= (T add_num,fraction<T> add_frac){
		return add_frac=add_frac*add_num;
	}
	// operator /=
	fraction<T> operator /= (fraction<T> add_num){
		return *this=*this/add_num;
	}
	fraction<T> operator /= (T add_num){
		return *this=*this/add_num;
	}
	friend fraction<T> operator /= (T add_num,fraction<T> add_frac){
		return add_frac=add_frac/add_num;
	}
	private:
	template<typename T1,typename T2=T1>
	struct two_fracs{
		fraction<T1> first;
		fraction<T2> second;
		two_fracs(){}
		two_fracs(fraction<T1> new_1,fraction<T2> new_2){
			first=new_1,second=new_2;
		}
	};
	template<typename T1,typename T2=T1>
	static two_fracs<T1,T2> common_value(fraction<T1> frac_x,fraction<T2> frac_y){
		T1 gcd_num=math::gcd(frac_x._down,frac_y._down);
		T1 x_multi_num=frac_y._down/gcd_num,y_multi_num=frac_x._down/gcd_num;
		frac_x._down*=x_multi_num,frac_x._up*=x_multi_num;
		frac_y._down*=y_multi_num,frac_y._up*=y_multi_num;
		return two_fracs<T1,T2>(frac_x,frac_y);
	}
};

namespace math{
	template<typename T>
	fraction<T> reduction(fraction<T> the_frac){
		return the_frac.reduction();
	}
}
#endif

分數與浮點數之間的運算要用這樣的形式:

fraction<int> frac(1,2);
double doub=0.3;
cout<<frac.value()+doub; // 或 cout<<double(frac)+doub;

歡迎轉載,但請在文章中附加上本文連結: https://blog.csdn.net/weixin_41461277/article/details/84890580 。