fraction.py

# Implement Fraction of integers with arithmetic operations and comparisons.
# Author:  Yotam Medini  [email protected] -- Created: 2006/October/04

import string


def gcd(m, n):
    m = abs(m)
    n = abs(n)
    if m < n:
        t = m;  m = n;  n = t; # swap
    # Now we have:  m >= n >= 0
    while n > 0: # Euclid
        remainder = m % n
        m = n
        n = remainder
    return m


def safe_int(s):
    "Convert string to integer, return None if bad string"
    try:
        n = int(s)
    except:
        n = None
    return n


def str2nd(s):
    "Convert  'n1'  or  'n1/n2'   to  pair (d,n)  for fraction. None otherwise"

    ss = string.split(s, '/')
    n = None
    d = 1
    if 1 <= len(ss) <= 2:
        n = safe_int(ss[0])
        if len(ss) == 2:
            d = safe_int(ss[1])
    nd = None # for bad input
    if n != None and d != None:
        nd = (n, d)
    return nd


class Fraction:
    "Fraction of integers with arithmetic operations and comparisons"

    def __init__(self, n=0, d=1):
        self.n = n # Numerator
        self.d = d # Denominator > 0
        self.reduce()


    def strset(self, s):
        nd = str2nd(s)
        ok = (nd != None)
        if ok:
            self.n = nd[0]
            self.d = nd[1]
            self.reduce()
        return ok


    def reduce(self):
        r = gcd(self.n, self.d)
        if r > 1:
            self.n /= r
            self.d /= r
        if self.d < 0: # We want positive denominator
            self.d = -self.d
            self.n = -self.n


    def __str__(self):
        return "(%d/%d)" % (self.n, self.d)


    def zero(self):
        return self.n == 0


    def positive(self):
        return self.n > 0


    def negative(self):
        return self.n < 0


    def __neg__(self):
        return Fraction(-self.n, self.d)


    def __add__(self, other):
        n = self.n * other.d + other.n * self.d
        d = self.d * other.d
        return Fraction(n, d)


    def __sub__(self, other):
        return self + (-other)


    def __mul__(self, other):
        return Fraction(self.n * other.n, self.d * other.d)


    def __div__(self, other):
        return Fraction(self.n * other.d, self.d * other.n)


    def __cmp__(self, other):
        diff = self.n * other.d - other.n * self.d
        return diff


zero = Fraction(0)
one = Fraction(1)


if __name__ == '__main__':
    import sys

    def usage(a0, rc=1):
        sys.stderr.write("""
Usage:
  %s  <frac1> <frac2>

Where  <frac1> and <frac1> are fractions of the form:  d  or  d/n
with d and n integers.
"""[1:] % a0)
        sys.exit(rc)


    if len(sys.argv) != 3:
        usage(sys.argv[0])

    f1 = Fraction()
    f2 = Fraction()
    f1.strset(sys.argv[1])
    f2.strset(sys.argv[2])
    sys.stdout.write("""
zero = %s,  one = %s,
f1  = %s,  f2 = %s
-f1 = %s, -f2 = %s

f1 + f2 = %s
f1 - f2 = %s
f1 * f2 = %s
f1 / f2 = %s

f1 == f2 = %s
f1 != f2 = %s
f1 <  f2 = %s
f1 <= f2 = %s
f1 >  f2 = %s
f1 >= f2 = %s
"""[1:] %
                     (
        zero, one,
        f1, f2, -f1, -f2,
        f1 + f2,  f1 - f2, f1 * f2, f1 / f2,
        (f1 == f2), (f1 != f2),
        f1 < f2, f1 <= f2, f1 > f2, f1 >= f2
    ))
    sys.exit(0)

Generated by GNU enscript 1.6.4.