Rat.py :  » Language-Interface » ChinesePython » chinesepython2.1.3-0.4 » Demo » classes » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Language Interface » ChinesePython 
ChinesePython » chinesepython2.1.3 0.4 » Demo » classes » Rat.py
'''\
This module implements rational numbers.

The entry point of this module is the function
  rat(numerator, denominator)
If either numerator or denominator is of an integral or rational type,
the result is a rational number, else, the result is the simplest of
the types float and complex which can hold numerator/denominator.
If denominator is omitted, it defaults to 1.
Rational numbers can be used in calculations with any other numeric
type.  The result of the calculation will be rational if possible.

There is also a test function with calling sequence
  test()
The documentation string of the test function contains the expected
output.
'''

# Contributed by Sjoerd Mullender

from types import *

def gcd(a, b):
  '''Calculate the Greatest Common Divisor.'''
  while b:
    a, b = b, a%b
  return a

def rat(num, den = 1):
  # must check complex before float
  if type(num) is ComplexType or type(den) is ComplexType:
    # numerator or denominator is complex: return a complex
    return complex(num) / complex(den)
  if type(num) is FloatType or type(den) is FloatType:
    # numerator or denominator is float: return a float
    return float(num) / float(den)
  # otherwise return a rational
  return Rat(num, den)

class Rat:
  '''This class implements rational numbers.'''

  def __init__(self, num, den = 1):
    if den == 0:
      raise ZeroDivisionError, 'rat(x, 0)'

    # normalize

    # must check complex before float
    if type(num) is ComplexType or type(den) is ComplexType:
      # numerator or denominator is complex:
      # normalized form has denominator == 1+0j
      self.__num = complex(num) / complex(den)
      self.__den = complex(1)
      return
    if type(num) is FloatType or type(den) is FloatType:
      # numerator or denominator is float:
      # normalized form has denominator == 1.0
      self.__num = float(num) / float(den)
      self.__den = 1.0
      return
    if (type(num) is InstanceType and
        num.__class__ is self.__class__) or \
       (type(den) is InstanceType and
        den.__class__ is self.__class__):
      # numerator or denominator is rational
      new = num / den
      if type(new) is not InstanceType or \
         new.__class__ is not self.__class__:
        self.__num = new
        if type(new) is ComplexType:
          self.__den = complex(1)
        else:
          self.__den = 1.0
      else:
        self.__num = new.__num
        self.__den = new.__den
    else:
      # make sure numerator and denominator don't
      # have common factors
      # this also makes sure that denominator > 0
      g = gcd(num, den)
      self.__num = num / g
      self.__den = den / g
    # try making numerator and denominator of IntType if they fit
    try:
      numi = int(self.__num)
      deni = int(self.__den)
    except (OverflowError, TypeError):
      pass
    else:
      if self.__num == numi and self.__den == deni:
        self.__num = numi
        self.__den = deni

  def __repr__(self):
    return 'Rat(%s,%s)' % (self.__num, self.__den)

  def __str__(self):
    if self.__den == 1:
      return str(self.__num)
    else:
      return '(%s/%s)' % (str(self.__num), str(self.__den))

  # a + b
  def __add__(a, b):
    try:
      return rat(a.__num * b.__den + b.__num * a.__den,
           a.__den * b.__den)
    except OverflowError:
      return rat(long(a.__num) * long(b.__den) +
           long(b.__num) * long(a.__den),
           long(a.__den) * long(b.__den))

  def __radd__(b, a):
    return Rat(a) + b

  # a - b
  def __sub__(a, b):
    try:
      return rat(a.__num * b.__den - b.__num * a.__den,
           a.__den * b.__den)
    except OverflowError:
      return rat(long(a.__num) * long(b.__den) -
           long(b.__num) * long(a.__den),
           long(a.__den) * long(b.__den))

  def __rsub__(b, a):
    return Rat(a) - b

  # a * b
  def __mul__(a, b):
    try:
      return rat(a.__num * b.__num, a.__den * b.__den)
    except OverflowError:
      return rat(long(a.__num) * long(b.__num),
           long(a.__den) * long(b.__den))

  def __rmul__(b, a):
    return Rat(a) * b

  # a / b
  def __div__(a, b):
    try:
      return rat(a.__num * b.__den, a.__den * b.__num)
    except OverflowError:
      return rat(long(a.__num) * long(b.__den),
           long(a.__den) * long(b.__num))

  def __rdiv__(b, a):
    return Rat(a) / b

  # a % b
  def __mod__(a, b):
    div = a / b
    try:
      div = int(div)
    except OverflowError:
      div = long(div)
    return a - b * div

  def __rmod__(b, a):
    return Rat(a) % b

  # a ** b
  def __pow__(a, b):
    if b.__den != 1:
      if type(a.__num) is ComplexType:
        a = complex(a)
      else:
        a = float(a)
      if type(b.__num) is ComplexType:
        b = complex(b)
      else:
        b = float(b)
      return a ** b
    try:
      return rat(a.__num ** b.__num, a.__den ** b.__num)
    except OverflowError:
      return rat(long(a.__num) ** b.__num,
           long(a.__den) ** b.__num)

  def __rpow__(b, a):
    return Rat(a) ** b

  # -a
  def __neg__(a):
    try:
      return rat(-a.__num, a.__den)
    except OverflowError:
      # a.__num == sys.maxint
      return rat(-long(a.__num), a.__den)

  # abs(a)
  def __abs__(a):
    return rat(abs(a.__num), a.__den)

  # int(a)
  def __int__(a):
    return int(a.__num / a.__den)

  # long(a)
  def __long__(a):
    return long(a.__num) / long(a.__den)

  # float(a)
  def __float__(a):
    return float(a.__num) / float(a.__den)

  # complex(a)
  def __complex__(a):
    return complex(a.__num) / complex(a.__den)

  # cmp(a,b)
  def __cmp__(a, b):
    diff = Rat(a - b)
    if diff.__num < 0:
      return -1
    elif diff.__num > 0:
      return 1
    else:
      return 0

  def __rcmp__(b, a):
       return cmp(Rat(a), b)

  # a != 0
  def __nonzero__(a):
    return a.__num != 0

  # coercion
  def __coerce__(a, b):
    return a, Rat(b)

def test():
  '''\
  Test function for rat module.

  The expected output is (module some differences in floating
  precission):
  -1
  -1
  0 0L 0.1 (0.1+0j)
  [Rat(1,2), Rat(-3,10), Rat(1,25), Rat(1,4)]
  [Rat(-3,10), Rat(1,25), Rat(1,4), Rat(1,2)]
  0
  (11/10)
  (11/10)
  1.1
  OK
  2 1.5 (3/2) (1.5+1.5j) (15707963/5000000)
  2 2 2.0 (2+0j)

  4 0 4 1 4 0
  3.5 0.5 3.0 1.33333333333 2.82842712475 1
  (7/2) (1/2) 3 (4/3) 2.82842712475 1
  (3.5+1.5j) (0.5-1.5j) (3+3j) (0.666666666667-0.666666666667j) (1.43248815986+2.43884761145j) 1
  1.5 1 1.5 (1.5+0j)

  3.5 -0.5 3.0 0.75 2.25 -1
  3.0 0.0 2.25 1.0 1.83711730709 0
  3.0 0.0 2.25 1.0 1.83711730709 1
  (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
  (3/2) 1 1.5 (1.5+0j)

  (7/2) (-1/2) 3 (3/4) (9/4) -1
  3.0 0.0 2.25 1.0 1.83711730709 -1
  3 0 (9/4) 1 1.83711730709 0
  (3+1.5j) -1.5j (2.25+2.25j) (0.5-0.5j) (1.50768393746+1.04970907623j) -1
  (1.5+1.5j) (1.5+1.5j)

  (3.5+1.5j) (-0.5+1.5j) (3+3j) (0.75+0.75j) 4.5j -1
  (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
  (3+1.5j) 1.5j (2.25+2.25j) (1+1j) (1.18235814075+2.85446505899j) 1
  (3+3j) 0j 4.5j (1+0j) (-0.638110484918+0.705394566962j) 0
  '''
  print rat(-1L, 1)
  print rat(1, -1)
  a = rat(1, 10)
  print int(a), long(a), float(a), complex(a)
  b = rat(2, 5)
  l = [a+b, a-b, a*b, a/b]
  print l
  l.sort()
  print l
  print rat(0, 1)
  print a+1
  print a+1L
  print a+1.0
  try:
    print rat(1, 0)
    raise SystemError, 'should have been ZeroDivisionError'
  except ZeroDivisionError:
    print 'OK'
  print rat(2), rat(1.5), rat(3, 2), rat(1.5+1.5j), rat(31415926,10000000)
  list = [2, 1.5, rat(3,2), 1.5+1.5j]
  for i in list:
    print i,
    if type(i) is not ComplexType:
      print int(i), float(i),
    print complex(i)
    print
    for j in list:
      print i + j, i - j, i * j, i / j, i ** j, cmp(i, j)

if __name__ == '__main__':
    test()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.