⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gnumber.cc

📁 Gambit 是一个游戏库理论软件
💻 CC
字号:
//// $Source: /home/gambit/CVS/gambit/sources/math/gnumber.cc,v $// $Date: 2002/08/26 05:50:03 $// $Revision: 1.4 $//// DESCRIPTION:// General number class//// This file is part of Gambit// Copyright (c) 2002, The Gambit Project//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//#ifdef __GNUG__#pragma implementation#endif#include <math.h>#include <values.h>#include <float.h>#include <ctype.h>#include "base/base.h"#include "gmath.h"#include "gnumber.h"gText gNumber::DivideByZero::Description(void) const{ return "Divide by zero in gNumber"; }//-------------------------------------------------------------------------//     gNumber: Constructors, Destructor, and Constructive Operators//-------------------------------------------------------------------------gNumber::gNumber(void)   : rep(precRATIONAL), rval(new gRational){ }gNumber::gNumber(float x)  : rep(precDOUBLE), dval(x){ }gNumber::gNumber(double x)  : rep(precDOUBLE), dval(x){ }gNumber::gNumber(int n)   : rep(precRATIONAL), rval(new gRational(n)){ }gNumber::gNumber(long n)   : rep(precRATIONAL), rval(new gRational(n)){ }gNumber::gNumber(const gInteger &y)  : rep(precRATIONAL), rval(new gRational(y)){ }gNumber::gNumber(const gRational &y)  : rep(precRATIONAL), rval(new gRational(y)){ }gNumber::gNumber(const gNumber &y)   : rep(y.rep){  if (rep == precDOUBLE)    dval = y.dval;  else    rval = new gRational(*y.rval);}gNumber::~gNumber() {  if (rep == precRATIONAL)  delete rval;}gNumber &gNumber::operator=(const gNumber &y){  if (this != &y)  {    if (rep == precRATIONAL)  {      delete rval;      rval = 0;    }    if (y.rep == precDOUBLE)      dval = y.dval;      else      rval = new gRational(*y.rval);    rep = y.rep;  }  return *this;}//-------------------------------------------------------------------------//                     gNumber: Operator overloading//-------------------------------------------------------------------------bool operator==(const gNumber &x, const gNumber &y){  if (x.rep != y.rep)   return false;  if (x.rep == precDOUBLE)    return x.dval == y.dval;  else     return *x.rval == *y.rval;}bool operator!=(const gNumber &x, const gNumber &y){  if (x.rep != y.rep)   return true;  if (x.rep == precDOUBLE)    return x.dval != y.dval;  else    return *x.rval != *y.rval;}bool operator<(const gNumber &x, const gNumber &y){  if (x.rep == precDOUBLE && y.rep == precDOUBLE)    return x.dval < y.dval;  else if (x.rep == precRATIONAL && y.rep == precRATIONAL)    return *(x.rval) < *(y.rval);  else if (x.rep == precRATIONAL && y.rep == precDOUBLE)    return y.dval > double(*(x.rval));  else // (x.rep == precDOUBLE && y.rep == precRATIONAL)    return x.dval < double(*(y.rval));}bool operator<=(const gNumber &x, const gNumber &y){  if (x.rep == precDOUBLE && y.rep == precDOUBLE)    return x.dval <= y.dval;  else if (x.rep == precRATIONAL && y.rep == precRATIONAL)    return *(x.rval) <= *(y.rval);  else if (x.rep == precRATIONAL && y.rep == precDOUBLE)  {    double eps;    gEpsilon(eps, 8);    return y.dval >= (double(*(x.rval)) - eps);  }  else // (x.rep == precDOUBLE && y.rep == precRATIONAL)  {    double eps;    gEpsilon(eps, 8);    return x.dval <= (double(*(y.rval)) + eps);  }}bool operator>(const gNumber &x, const gNumber &y){  if (x.rep == precDOUBLE && y.rep == precDOUBLE)    return x.dval > y.dval;  else if (x.rep == precRATIONAL && y.rep == precRATIONAL)    return *(x.rval) > *(y.rval);  else if (x.rep == precRATIONAL && y.rep == precDOUBLE)    return y.dval < double(*(x.rval));  else // (x.rep == precDOUBLE && y.rep == precRATIONAL)    return x.dval > double(*(y.rval));}bool operator>=(const gNumber &x, const gNumber &y){  if (x.rep == precDOUBLE && y.rep == precDOUBLE)    return x.dval >= y.dval;  else if (x.rep == precRATIONAL && y.rep == precRATIONAL)    return *(x.rval) >= *(y.rval);  else if (x.rep == precRATIONAL && y.rep == precDOUBLE) {    double eps;    gEpsilon(eps, 8);    return y.dval <= (double(*(x.rval)) + eps);  }  else { // (x.rep == precDOUBLE && y.rep == precRATIONAL)    double eps;    gEpsilon(eps, 8);    return x.dval >= (double(*(y.rval)) - eps);  }}gNumber &gNumber::operator+=(const gNumber &y) {  if (rep == precDOUBLE)   {    if (y.rep == precDOUBLE)      dval += y.dval;    else    // if (y.rep == precRATIONAL)      dval += double(*y.rval);  }  else   {  // this is a rational    if (y.rep == precDOUBLE)   {      double dtmp = double(*rval) + y.dval;      rep = precDOUBLE;      delete rval;      dval = dtmp;    }    else // if (y.rep == precRATIONAL;      *rval += *y.rval;  }  return *this;}gNumber &gNumber::operator-=(const gNumber &y) {  if (rep == precDOUBLE)  {    if (y.rep == precDOUBLE)      dval -= y.dval;    else    // if (y.rep == precRATIONAL)      dval -= double(*y.rval);  }  else  {  // this is a rational    if (y.rep == precDOUBLE)  {      double dtmp = double(*rval) - y.dval;      rep = precDOUBLE;      delete rval;      dval = dtmp;    }    else    // if (y.rep == precRATIONAL)      *rval -= *y.rval;  }  return *this;}gNumber &gNumber::operator*=(const gNumber &y) {  if (rep == precDOUBLE)   {    if (y.rep == precDOUBLE)      dval *= y.dval;    else    // if (y.rep == precRATIONAL)      dval *= double(*y.rval);  }  else   {  // this is a rational    if (y.rep == precDOUBLE)  {      double dtmp = double(*rval) * y.dval;      rep = precDOUBLE;      delete rval;      dval = dtmp;    }    else    // if (y.rep == precRATIONAL)      *rval *= *y.rval;  }  return *this;}gNumber &gNumber::operator/=(const gNumber &y) {  if (rep == precDOUBLE)   {    if (y.rep == precDOUBLE)  {      if (y.dval == 0.0)   throw DivideByZero();      dval /= y.dval;    }    else   {   // if (y.rep == precRATIONAL)      if (*y.rval == gRational(0))     throw DivideByZero();      dval /= double(*y.rval);    }  }  else  {   // this is a rational     if (y.rep == precDOUBLE)  {      if (y.dval == 0.0)   throw DivideByZero();      double dtmp = double(*rval) / y.dval;      rep = precDOUBLE;      delete rval;      dval = dtmp;     }    else   {  // if (y.rep == precRATIONAL)      if (*y.rval == gRational(0))    throw DivideByZero();      *rval /= *y.rval;    }  }  return *this;}gNumber operator+(const gNumber &x, const gNumber &y) {  if (x.rep == precDOUBLE)   {    if (y.rep == precDOUBLE)      return gNumber(x.dval + y.dval);    else   // if (y.rep == precRATIONAL)      return gNumber(x.dval + double(*y.rval));  }  else   {    if (y.rep == precDOUBLE)        return gNumber(double(*x.rval) + y.dval);    else   // if (y.rep == precRATIONAL)      return gNumber(*x.rval + *y.rval);  }}gNumber operator-(const gNumber &x, const gNumber &y){  if (x.rep == precDOUBLE)   {    if (y.rep == precDOUBLE)      return gNumber(x.dval - y.dval);    else   // if (y.rep == precRATIONAL)      return gNumber(x.dval - double(*y.rval));  }  else  {    if (y.rep == precDOUBLE)      return gNumber(double(*x.rval) - y.dval);    else   // if (y.rep == precRATIONAL)      return gNumber(*x.rval - *y.rval);  }}gNumber operator*(const gNumber &x, const gNumber &y){  if (x.rep == precDOUBLE)  {    if (y.rep == precDOUBLE)      return gNumber(x.dval * y.dval);    else    // if (y.rep == precRATIONAL)      return gNumber(x.dval * double(*y.rval));  }  else  {    if (y.rep == precDOUBLE)        return gNumber(double(*x.rval) * y.dval);    else    // if (y.rep == precRATIONAL\)      return gNumber(*x.rval * *y.rval);  }}gNumber operator/(const gNumber &x, const gNumber &y){  if (x.rep == precDOUBLE)   {    if (y.rep == precDOUBLE)   {      if (y.dval == 0.0)    throw gNumber::DivideByZero();      return gNumber(x.dval / y.dval);     }    else  {   // if (y.rep == precRATIONAL)      if (*y.rval == gRational(0))    throw gNumber::DivideByZero();      return gNumber(x.dval / double(*y.rval));    }  }  else   {    if (y.rep == precDOUBLE)   {      if (y.dval == 0.0)   throw gNumber::DivideByZero();      return gNumber(double(*x.rval) / y.dval);    }    else  { // if (y.rep == precRATIONAL)      if (*y.rval == gRational(0))   throw gNumber::DivideByZero();      return gNumber(*x.rval / *y.rval);    }  }}gNumber operator-(const gNumber &x){  gNumber r(x);  if (x.rep == precDOUBLE)    r.dval = -x.dval;  else    *r.rval = -*x.rval;  return r;}gOutput& operator<<(gOutput& s, const gNumber &x){  if (x.Precision() == precDOUBLE)    s << x.dval;  else    s << *x.rval;  return s;}  //  Basically identical to the rational >> operator, but sets y to be   // either a double or rational depending on input.gInput& operator>>(gInput& f, gNumber &y){  char ch = ' ';  int sign = 1;  bool isDouble = false;  gInteger num = 0, denom = 1;  long old_pos = f.getpos();  while (isspace(ch))    f >> ch;    if (ch != '-' && !isdigit(ch) && ch != '.') {    f.setpos(old_pos);    throw gFileInput::ReadFailed();  }  if (ch == '-')  {     sign = -1;    f >> ch;  }    while (ch >= '0' && ch <= '9')   {    num *= 10;    num += (int) (ch - '0');    f >> ch;  }    if (ch == '/')  {    denom = 0;    f >> ch;    while (ch >= '0' && ch <= '9')  {      denom *= 10;      denom += (int) (ch - '0');      f >> ch;    }  }  else if (ch == '.')  {      double dval;    f.setpos(old_pos);    f >> dval;    y = dval;    return f;  }  f.unget(ch);  gRational geez;  geez = gRational(sign * num, denom);    if (isDouble == true)   {    y = (double) geez;    y.rep = precDOUBLE;  }  else  {    y = geez;    y.rep = precRATIONAL;  }  return f;}//-------------------------------------------------------------------------//           gNumber: Miscellaneous mathematical functions //-------------------------------------------------------------------------gNumber pow(const gNumber &x, long n){  if (x.rep == precDOUBLE)    return pow(x.dval, n);  else    return pow(*x.rval, n);}//-------------------------------------------------------------------------//           gNumber: Precision-related functions and casts//-------------------------------------------------------------------------gNumber::operator double(void) const{  if (rep == precDOUBLE)    return dval;  else    return (double) *rval;}gNumber::operator gRational(void) const{  if (rep == precDOUBLE)    return gRational(dval);  else    return *rval;}bool gNumber::IsInteger(void) const{  return ((rep == precDOUBLE && fmod(dval, 1.0) == 0.0) ||	  (rep == precRATIONAL && rval->denominator() == 1));}gText ToText(const gNumber &n){  if (n.Precision() == precDOUBLE)    return ToText((double) n);  else    return ToText(n.operator gRational());}gText ToText(const gNumber &p_number, int p_precision){  if (p_number.Precision() == precDOUBLE)    return ToText((double) p_number, p_precision);  else    return ToText(p_number.operator gRational());}// Rational if there is no decimal pointgNumber FromText(const gText &s,gNumber &n){  gRational r;  double d;  gText tmp=s;  if (tmp.LastOccur('.'))    n=FromText(s,d);  else    n=FromText(s,r);  return n;}gNumber ToNumber(const gText &p_string){  gNumber tmp;  return FromText(p_string, tmp);}void gEpsilon(gNumber &n, int i){  if (n.Precision() == precRATIONAL)    n = (gRational)0;  else    n = pow(10.0,(double)-i);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -