[Tutor] fractions

Michael P. Reilly arcege@speakeasy.net
Thu, 26 Apr 2001 09:11:04 -0400 (EDT)


--%--multipart-mixed-boundary-1.1422.988290664--%
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

> Hi all,
> 
> Does anyone know of a function to convert fractions to decimals and =
> decimals to fractions?

There is no nice function to do it, simply because there are no fractions
in Python (maybe in P3K?).  But a couple of years ago (Jan '99), there
were questions about rational numbers in Python and I whipped up a little
class which I'm attaching.

If you mean simply the division of integers (as opposed to fractions as
a data type).  Then you can do something as simple as:
  x / float(y)

Division of a float with any other object (except a complex number)
will result in a float.  Converting back to a "fraction" is something
else - there has to be the exception where it is not possible.  In fact,
I just realized that my rational class doesn't even do this.

  -Arcege

-- 
+----------------------------------+-----------------------------------+
| Michael P. Reilly                | arcege@speakeasy.net              |

--%--multipart-mixed-boundary-1.1422.988290664--%
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Description: a /usr/local/bin/python script text
Content-Disposition: attachment; filename="rational.py"

#!/usr/local/bin/python
# Copyright (C) 1999 Michael P. Reilly, All rights reserved

class Rational:
  def __init__(self, numerator, denominator=1):
    if denominator == 0:
      raise ValueError, 'undefined value'
    if isinstance(numerator, Rational):
      denominator = denominator * numerator.d
      numerator = numerator.n
    if int(numerator) != numerator or int(denominator) != int(denominator):
      raise ValueError, 'must supply integer values (for now)'
    self.n = int(numerator)
    self.d = int(denominator)
    self.normalize()
  def __int__(self):
    return int(self.n/self.d)
  def __float__(self):
    return float(self.n)/self.d
  def __str__(self):
    if self.d == 1:
      return '%d' % self.n
    else:
      return '%d/%d' % (self.n, self.d)
  def __repr__(self):
    return '%s(%d, %d)' % (self.__class__.__name__, self.n, self.d)
  def __cmp__(self, other):
    s, o, d = self.gcd(other)
    return cmp(s, o)
  def __rcmp__(self, other):
    s, o, d = self.gcd(other)
    return cmp(o, s)

  def normalize(self):
    num = self.n
    dem = self.d
    # this isn't the best algorithm
    i = dem
    while i > 0:
      if (num % i) == 0 and (dem % i) == 0:
        break
      i = i - 1
    else:
      return
    self.n = int(num/i)
    self.d = int(dem/i)
  def gcd(self, other):
    sn = self.n  * other.d
    on = other.n * self.d
    d  = self.d  * other.d
    return (sn, on, d)

  def __add__(self, other):
    s, o, d = self.gcd(other)
    r = self.__class__(s+o, d)
    return r
  __radd__ = __add__
  def __sub__(self, other):
    s, o, d = self.gcd(other)
    r = self.__class__(s-o, d)
    return r
  def __rsub__(self, other):
    s, o, d = self.gcd(other)
    r = self.__class__(o-s, d)
    return r
  def __mul__(self, other):
    r = self.__class__(self.n*other.n, self.d*other.d)
    return r
  __rmul__ = __mul__

  def __div__(self, other):
    r = self.__class__(self.n*other.d, self.d*other.n)
    return r
  def __rdiv__(self, other):
    r = self.__class__(other.n*self.d, other.d*self.n)
    return r
  def __mod__(self, other):
    r = divmod(self, other)
    return r[1]
  def __rmod__(self, other):
    r = divmod(other, self)
    return r[1]
  def __divmod__(self, other):
    r = self / other
    whole = r.n / r.d
    remainder = r.n % r.d
    return (whole, remainder)
  def __rdivmod__(self, other):
    r = other / self
    whole = r.n / r.d
    remainder = r.n % r.d
    return (whole, remainder)

  def __pow__(self, other):
    if other.d < 0:  # great, now check for complex
      if other.d == -1:
        return complex(0, float(self))
      else:
        raise ValueError, 'not implimented'
    sn = pow(self.n, float(other))
    sd = pow(self.d, float(other))
    r = self.__class__(sn, sd)
    return r
  def __rpow__(self, other):
    return other ** self

  def __neg__(self):
    r = self.__class__(-self.n, self.d)
    return r
  def __pos__(self):
    r = self.__class__(self.n, self.d)
    return r
  def __abs__(self):
    r = self.__class__(abs(self.n), abs(self.d))
    return r

  def __coerce__(self, other):
    if isinstance(other, Rational):
      return self, other
    elif type(other) is type(0):
      return self, self.__class__(other)
    elif type(other) is type(0L):
      return self, self.__class__(other)
    elif type(other) is type(0.0):
      raise ValueError, 'not implimented'
    elif type(other) == type(0j):
      raise ValueError, 'not implimented'
      return self, self.__class__(other.real, other.imag)


--%--multipart-mixed-boundary-1.1422.988290664--%--