在几乎所有的语言中(至少我知道的语言都是这样),浮点数都是有精度丢失的。
怎么解决呢?
分数类就是解决办法之一。
分数类采用分数的形式,保存了两个整数之比,确保了精度。
分数类,肯定是要有约分、通分等函数和加、减、乘、除运算符的。(当然,要先实现求最大公因数和最小公倍数函数)这些都是基本数学知识。
代码如下:
#ifndef FRACTION_H
#define FRACTION_H
#include
#include
using std::istream;
using std::ostream;
using std::getchar;
namespace math{
template
T gcd(T x,T y){
if(x
T lcm(T x,T y){
return x/gcd(x,y)*y;
}
}
template //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& the_frac){
if(the_frac.input_with_reduction) the_frac.reduction();
input>>the_frac._up;
getchar();
input>>the_frac._down;
return input;
}
fraction 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 the_frac){
if(the_frac.output_with_reduction) the_frac.reduction();
output< 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
Tans value()const{
return Tans(_up)/Tans(_down);
}
fraction reduction(){ //约分
T gcd_result=math::gcd(_up,_down);
_up/=gcd_result,_down/=gcd_result;
return *this;
}
fraction reciprocal(bool with_reduction=1)const{
return fraction(_down,_up,with_reduction,1);
}
template
static void common(fraction &frac_x,fraction &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 operator + (T another_adder)const{
fraction frac_adder(another_adder*_down,_down,0,0);
return fraction(_up+frac_adder._up,_down,1,1);
}
fraction operator + (fraction another_adder)const{
two_fracs commoned=common_value(*this,another_adder);
return fraction(commoned.first._up+commoned.second._up,commoned.first._down,true,true);
}
friend fraction operator + (T adder,fraction frac_adder){
fraction frac_adder_eq1(adder*frac_adder._down,frac_adder._down,false,false);
return fraction(frac_adder._up+frac_adder_eq1._up,frac_adder._down,true,true);
}
//operator -
fraction operator - (fraction another_adder)const{
two_fracs commoned=common_value(*this,another_adder);
return fraction(commoned.first._up-commoned.second._up,commoned.first._down,true,true);
}
friend fraction operator - (T adder,fraction frac_adder){
fraction frac_adder_eq1(adder*frac_adder._down,frac_adder._down,false,false);
return fraction(frac_adder_eq1._up-frac_adder._up,frac_adder._down,true,true);
}
//operator *
fraction 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(_up*another_adder,_down,false,false);
}
fraction operator * (fraction 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(_up*another_adder._up,_down*another_adder._down,false,false);
}
else{
return fraction(_up*another_adder._up,_down*another_adder._down,true,true);
}
}
friend fraction operator * (T adder,fraction 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(frac_adder._up*adder,frac_adder._down,false,false);
}
//operator /
fraction operator / (T divider){
return operator * (fraction(divider,1,multi_optimize));
}
fraction operator / (fraction divider){
return operator * (divider.reciprocal(!multi_optimize));
}
friend fraction operator / (T dividend,fraction divider){
return operator * (dividend,divider.reciprocal(false));
}
// operator < , == , != , > , <= , >=
// operator <
bool operator < (fraction frac_arg)const{
two_fracs commoned=common_value(*this,frac_arg);
return commoned.first._up frac_arg_eqint(integer_arg*_down,_down,false,false);
return _up frac_arg){
fraction frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
return frac_arg._up frac_arg)const{
two_fracs commoned=common_value(*this,frac_arg);
return commoned.first._up==commoned.second._up;
}
bool operator == (T integer_arg)const{
fraction frac_arg_eqint(integer_arg*_down,_down,false,false);
return _up==frac_arg_eqint._up;
}
friend bool operator == (T integer_arg,fraction frac_arg){
fraction 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 frac_arg)const{
two_fracs commoned=common_value(*this,frac_arg);
return commoned.first._up!=commoned.second._up;
}
bool operator != (T integer_arg)const{
fraction frac_arg_eqint(integer_arg*_down,_down,false,false);
return _up!=frac_arg_eqint._up;
}
friend bool operator != (T integer_arg,fraction frac_arg){
fraction 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 frac_arg)const{
two_fracs commoned=common_value(*this,frac_arg);
return commoned.first._up>commoned.second._up;
}
bool operator > (T integer_arg)const{
fraction frac_arg_eqint(integer_arg*_down,_down,false,false);
return _up>frac_arg_eqint._up;
}
friend bool operator > (T integer_arg,fraction frac_arg){
fraction 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 frac_arg)const{
two_fracs commoned=common_value(*this,frac_arg);
return commoned.first._up<=commoned.second._up;
}
bool operator <= (T integer_arg)const{
fraction frac_arg_eqint(integer_arg*_down,_down,false,false);
return _up<=frac_arg_eqint._up;
}
friend bool operator <= (T integer_arg,fraction frac_arg){
fraction 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 frac_arg)const{
two_fracs commoned=common_value(*this,frac_arg);
return commoned.first._up>=commoned.second._up;
}
bool operator >= (T integer_arg)const{
fraction frac_arg_eqint(integer_arg*_down,_down,false,false);
return _up>=frac_arg_eqint._up;
}
friend bool operator >= (T integer_arg,fraction frac_arg){
fraction frac_arg_eqint(integer_arg*frac_arg._down,frac_arg._down,false,false);
return frac_arg._up>=frac_arg_eqint._up;
}
// operator += , -= , *= , /=
// operator +=
fraction operator += (fraction add_num){
return *this=*this+add_num;
}
fraction operator += (T add_num){
return *this=*this+add_num;
}
friend fraction operator += (T add_num,fraction add_frac){
return add_frac=add_frac+add_num;
}
// operator -=
fraction operator -= (fraction add_num){
return *this=*this-add_num;
}
fraction operator -= (T add_num){
return *this=*this-add_num;
}
friend fraction operator -= (T add_num,fraction add_frac){
return add_frac=add_frac-add_num;
}
// operator *=
fraction operator *= (fraction add_num){
return *this=*this*add_num;
}
fraction operator *= (T add_num){
return *this=*this*add_num;
}
friend fraction operator *= (T add_num,fraction add_frac){
return add_frac=add_frac*add_num;
}
// operator /=
fraction operator /= (fraction add_num){
return *this=*this/add_num;
}
fraction operator /= (T add_num){
return *this=*this/add_num;
}
friend fraction operator /= (T add_num,fraction add_frac){
return add_frac=add_frac/add_num;
}
private:
template
struct two_fracs{
fraction first;
fraction second;
two_fracs(){}
two_fracs(fraction new_1,fraction new_2){
first=new_1,second=new_2;
}
};
template
static two_fracs common_value(fraction frac_x,fraction 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(frac_x,frac_y);
}
};
namespace math{
template
fraction reduction(fraction the_frac){
return the_frac.reduction();
}
}
#endif
注意:分数与浮点数之间的运算要用这样的形式:
fraction frac(1,2);
double doub=0.3;
cout<
欢迎转载,但请在文章中附加上本文链接: https://blog.csdn.net/weixin_41461277/article/details/84890580 。