Back to SDS/2 Parametric Scripts

 

class Rational(object):

    """

    Class definition for the manipulation of rational numbers.

    Any number that can be exactly represented by a ratio of integers is rational.

    Under the operations +, -, *, and /, rational numbers are closed meaning the

    result is another rational number.

    """

 

    def __init__(self, num, den=1):

        if den != 0:

            if isinstance(num, float) or isinstance(den, float):

                num, den = map(lambda x: x * 100000, [num, den])

                num, den = map(int, [num, den])

 

            reduced = self.__gcd__(num, den)

            self.n = num/reduced

            self.d = den/reduced

        else:

            raise ValueError, 'The denominator must not be 0'

 

    def __gcd__(self, a, b):

        while b:

            a, b = b, a%b

        return abs(a)       

 

    def __repr__(self):

        return 'Rational(%d, %d)' % (self.n, self.d)

 

    def __str__(self):

        return '(%d/%d)' % (self.n, self.d)

 

    def __add__(self, other):

        other = self.__coerce__(other)

        return Rational(self.n * other.d + other.n * self.d, self.d * other.d)

 

    def __sub__(self, other):

        other = self.__coerce__(other)

        return Rational(self.n * other.d - other.n * self.d, self.d * other.d)

       

    def __mul__(self, other):

        other = self.__coerce__(other)

        return Rational(self.n * other.n, self.d * other.d)

 

    def __div__(self, other):

        other = self.__coerce__(other)

        # invert other and multiply

        return Rational(self.n * other.d, self.d * other.n)

 

    # This method will return a Rational object that may be an approximation

    # of the calculation result

    def __pow__(self, exp):

        return Rational((self.n / float(self.d))**exp)

 

    def __cmp__(self, other):

        other = self.__coerce__(other)

        return cmp(self.n / float(self.d), other.n / float(other.d))

 

    def __neg__(self):

        return Rational(-self.n, self.d)

 

    def __coerce__(self, other):

        if isinstance(other, Rational):

            return other

        try:

            return Rational(other)

        except:

            raise ValueError, 'Invalid operand'

 

    def eval(self):       

        return self.n/float(self.d)

 

""">>> a = Rational(3,4)

>>> b = Rational(5,6)

>>> a

Rational(3, 4)

>>> b

Rational(5, 6)

>>> a+b

Rational(19, 12)

>>> a-b

Rational(-1, 12)

>>> b-a

Rational(1, 12)

>>> a*b

Rational(5, 8)

>>> b*a

Rational(5, 8)

>>> a/b

Rational(9, 10)

>>> b/a

Rational(10, 9)

>>> a**2

Rational(9, 16)

>>> b**0.5

Rational(91287, 100000)

>>> a<b

True

>>> b<a

False

>>> a>b

False

>>> print a

(3/4)

>>> print b

(5/6)

>>>

>>> a = Rational(4,5)

>>> a.eval()

0.80000000000000004

>>> c = Rational(12,13)

>>> c.eval()

0.92307692307692313

>>>

>>> a = Rational(72,124)

>>> a

Rational(18, 31)

>>> -a

Rational(-18, 31)

>>> print -a

(-18/31)

>>>

"""