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

📄 rational.cc

📁 早期freebsd实现
💻 CC
字号:
/* Copyright (C) 1988 Free Software Foundation    written by Doug Lea (dl@rocky.oswego.edu)This file is part of the GNU C++ Library.  This library is freesoftware; you can redistribute it and/or modify it under the terms ofthe GNU Library General Public License as published by the FreeSoftware Foundation; either version 2 of the License, or (at youroption) any later version.  This library is distributed in the hopethat it will be useful, but WITHOUT ANY WARRANTY; without even theimplied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULARPURPOSE.  See the GNU Library General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA.*/#ifdef __GNUG__#pragma implementation#endif#include <Rational.h>#include <std.h>#include <math.h>#include <values.h>#include <builtin.h>#include <float.h>void Rational::error(const char* msg) const{  (*lib_error_handler)("Rational", msg);}static const Integer _Int_One(1);void Rational::normalize(){  int s = sign(den);  if (s == 0)    error("Zero denominator.");  else if (s < 0)  {    den.negate();    num.negate();  }  Integer g = gcd(num, den);  if (ucompare(g, _Int_One) != 0)  {    num /= g;    den /= g;  }}void      add(const Rational& x, const Rational& y, Rational& r){  if (&r != &x && &r != &y)  {    mul(x.num, y.den, r.num);    mul(x.den, y.num, r.den);    add(r.num, r.den, r.num);    mul(x.den, y.den, r.den);  }  else  {    Integer tmp;    mul(x.den, y.num, tmp);    mul(x.num, y.den, r.num);    add(r.num, tmp, r.num);    mul(x.den, y.den, r.den);  }  r.normalize();}void      sub(const Rational& x, const Rational& y, Rational& r){  if (&r != &x && &r != &y)  {    mul(x.num, y.den, r.num);    mul(x.den, y.num, r.den);    sub(r.num, r.den, r.num);    mul(x.den, y.den, r.den);  }  else  {    Integer tmp;    mul(x.den, y.num, tmp);    mul(x.num, y.den, r.num);    sub(r.num, tmp, r.num);    mul(x.den, y.den, r.den);  }  r.normalize();}void      mul(const Rational& x, const Rational& y, Rational& r){  mul(x.num, y.num, r.num);  mul(x.den, y.den, r.den);  r.normalize();}void      div(const Rational& x, const Rational& y, Rational& r){  if (&r != &x && &r != &y)  {    mul(x.num, y.den, r.num);    mul(x.den, y.num, r.den);  }  else  {    Integer tmp;    mul(x.num, y.den, tmp);    mul(y.num, x.den, r.den);    r.num = tmp;  }  r.normalize();}void Rational::invert(){  Integer tmp = num;    num = den;    den = tmp;    int s = sign(den);  if (s == 0)    error("Zero denominator.");  else if (s < 0)  {    den.negate();    num.negate();  }}int compare(const Rational& x, const Rational& y){  int xsgn = sign(x.num);  int ysgn = sign(y.num);  int d = xsgn - ysgn;  if (d == 0 && xsgn != 0) d = compare(x.num * y.den, x.den * y.num);  return d;}Rational::Rational(double x){  num = 0;  den = 1;  if (x != 0.0)  {    int neg = x < 0;    if (neg)      x = -x;    const long shift = 15;         // a safe shift per step    const double width = 32768.0;  // = 2^shift    const int maxiter = 20;        // ought not be necessary, but just in case,                                   // max 300 bits of precision    int expt;    double mantissa = frexp(x, &expt);    long exponent = expt;    double intpart;    int k = 0;    while (mantissa != 0.0 && k++ < maxiter)    {      mantissa *= width;      mantissa = modf(mantissa, &intpart);      num <<= shift;      num += (long)intpart;      exponent -= shift;    }    if (exponent > 0)      num <<= exponent;    else if (exponent < 0)      den <<= -exponent;    if (neg)      num.negate();  }  normalize();}Integer trunc(const Rational& x){  return x.num / x.den ;}Rational pow(const Rational& x, const Integer& y){  long yy = long(y);  return pow(x, yy);}               #if defined(__GNUG__) && !defined(NO_NRV)Rational operator - (const Rational& x) return r(x){  r.negate();}Rational abs(const Rational& x) return r(x){  if (sign(r.num) < 0) r.negate();}Rational sqr(const Rational& x) return r{  mul(x.num, x.num, r.num);  mul(x.den, x.den, r.den);  r.normalize();}Integer floor(const Rational& x) return q{  Integer r;  divide(x.num, x.den, q, r);  if (sign(x.num) < 0 && sign(r) != 0) q--;}Integer ceil(const Rational& x) return q{  Integer  r;  divide(x.num, x.den, q, r);  if (sign(x.num) >= 0 && sign(r) != 0) q++;}Integer round(const Rational& x) return q{  Integer r;  divide(x.num, x.den, q, r);  r <<= 1;  if (ucompare(r, x.den) >= 0)  {    if (sign(x.num) >= 0)      q++;    else      q--;  }}// power: no need to normalize since num & den already relatively primeRational pow(const Rational& x, long y) return r{  if (y >= 0)  {    pow(x.num, y, r.num);    pow(x.den, y, r.den);  }  else  {    y = -y;    pow(x.num, y, r.den);    pow(x.den, y, r.num);    if (sign(r.den) < 0)    {      r.num.negate();      r.den.negate();    }  }}#elseRational operator - (const Rational& x) {  Rational r(x); r.negate(); return r;}Rational abs(const Rational& x) {  Rational r(x);  if (sign(r.num) < 0) r.negate();  return r;}Rational sqr(const Rational& x){  Rational r;  mul(x.num, x.num, r.num);  mul(x.den, x.den, r.den);  r.normalize();  return r;}Integer floor(const Rational& x){  Integer q;  Integer r;  divide(x.num, x.den, q, r);  if (sign(x.num) < 0 && sign(r) != 0) q--;  return q;}Integer ceil(const Rational& x){  Integer q;  Integer  r;  divide(x.num, x.den, q, r);  if (sign(x.num) >= 0 && sign(r) != 0) q++;  return q;}Integer round(const Rational& x) {  Integer q;  Integer r;  divide(x.num, x.den, q, r);  r <<= 1;  if (ucompare(r, x.den) >= 0)  {    if (sign(x.num) >= 0)      q++;    else      q--;  }  return q;}Rational pow(const Rational& x, long y){  Rational r;  if (y >= 0)  {    pow(x.num, y, r.num);    pow(x.den, y, r.den);  }  else  {    y = -y;    pow(x.num, y, r.den);    pow(x.den, y, r.num);    if (sign(r.den) < 0)    {      r.num.negate();      r.den.negate();    }  }  return r;}#endifostream& operator << (ostream& s, const Rational& y){  if (y.denominator() == 1)    s << y.numerator();  else  {    s << y.numerator();    s << "/";    s << y.denominator();  }  return s;}istream& operator >> (istream& s, Rational& y){#ifdef _OLD_STREAMS  if (!s.good())  {    return s;  }#else  if (!s.ipfx(0))  {    s.set(ios::failbit); // Redundant if using GNU iostreams.    return s;  }#endif  Integer n = 0;  Integer d = 1;  if (s >> n)  {    char ch = 0;    s.get(ch);    if (ch == '/')    {      s >> d;    }    else    {      s.putback(ch);    }  }  y = Rational(n, d);  return s;}int Rational::OK() const{  int v = num.OK() && den.OK(); // have valid num and denom  if (v)    {      v &= sign(den) > 0;           // denominator positive;      v &=  ucompare(gcd(num, den), _Int_One) == 0; // relatively prime    }  if (!v) error("invariant failure");  return v;}intRational::fits_in_float() const{    return FLT_MIN <= *this && *this <= FLT_MAX;}intRational::fits_in_double() const{    return DBL_MIN <= *this && *this <= DBL_MAX;}

⌨️ 快捷键说明

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