Using fractions instead of floats

mensanator at aol.com mensanator at aol.com
Mon Oct 1 20:58:07 EDT 2007


On Oct 1, 7:09 pm, andresj <andres.j.... at gmail.com> wrote:
> > > On 2007-10-01, Arnaud Delobelle <arno... at googlemail.com> wrote:
>
> > > > Finally, arithmetic would become very confusing if there were
> > > > three distinct numeric types; it already causes enough
> > > > confusion with two!
>
> Well, yeah... I get what you are saying, that would be confusing...
>
> Terry Reedy and Laurent Pointal:
> I know from __future__ import division changes the behaivour to return
> floats instead of ints, but what I meant is to be able to implement a
> function (or class/method) which would return what _I_ want/decide.
>
> Gabriel Genellina, thanks for the suggestion of wrapping my code. I
> think it could be one way... But I think it would be too much trouble,
> I'll just go with writing fractions/rationals explicitly.
>
> And thanks to mensanator and Gabriel for the suggestion of gmpy, and
> to Nick for the example (It really helps to have an example,

Would you like to see a more thorough example?

First, go check out the Wikipedia article:
<http://en.wikipedia.org/wiki/Collatz_conjecture>

And scroll down the the section "Iterating on rational numbers
with odd denominators". I added the section beginning with
"The complete cycle being:..." through "And this is because...".

Here's the Python program I used to develop that section.

import gmpy

def calc_pv_xyz(pv):
    """calculate Hailstone Function Parameters
       using Parity Vector instead of Sequence Vector
       (defined using (3n+1)/2)

    calc_pv_xyz(pv)
    pv: parity vector
    returns HailstoneFunctionParameters (x,y,z)
    """
    ONE = gmpy.mpz(1)
    TWO = gmpy.mpz(2)
    TWE = gmpy.mpz(3)
    twee = gmpy.mpz(sum(pv))
    twoo = gmpy.mpz(len(pv))
    x = TWO**twoo
    y = TWE**twee
    z = gmpy.mpz(0)
    c = gmpy.mpz(sum(pv)-1)
    for i,j in enumerate(pv):
      if j:
        z += TWE**c * TWO**i
        c -= ONE
    return (x,y,z)

def iterating_on_rational(n): # Collatz for rational numbers
  # is numerator odd?
  if n.numer() % 2 == 1:
    n = (n*3 + 1)/2
  else:
    n = n/2
  print n,
  return n

pv = [1,0,1,1,0,0,1]

for i in xrange(len(pv)+1):
  print pv
  # get Hailstone Function parameters X,Y,Z
  xyz = calc_pv_xyz(pv)
  # calculate the Crossover Point Z/(X-Y)
  cp = gmpy.mpq(xyz[2],xyz[0]-xyz[1])     # as a rational number
  # start of loop cycle
  print cp,
  # start the cycle...
  n = iterating_on_rational(cp)
  # ...which MUST return to the starting point
  # since ALL rationals are valid Crossover Points
  # not just integers
  while n != cp:
    n = iterating_on_rational(n)
  print
  print
  # step through the cyclic permutations
  p = pv.pop(0)
  pv.append(p)

##  parity vector cyclic permutations
##
##  [1, 0, 1, 1, 0, 0, 1]
##  151/47 250/47 125/47 211/47 340/47 170/47 85/47 151/47
##
##  [0, 1, 1, 0, 0, 1, 1]
##  250/47 125/47 211/47 340/47 170/47 85/47 151/47 250/47
##
##  [1, 1, 0, 0, 1, 1, 0]
##  125/47 211/47 340/47 170/47 85/47 151/47 250/47 125/47
##
##  [1, 0, 0, 1, 1, 0, 1]
##  211/47 340/47 170/47 85/47 151/47 250/47 125/47 211/47
##
##  [0, 0, 1, 1, 0, 1, 1]
##  340/47 170/47 85/47 151/47 250/47 125/47 211/47 340/47
##
##  [0, 1, 1, 0, 1, 1, 0]
##  170/47 85/47 151/47 250/47 125/47 211/47 340/47 170/47
##
##  [1, 1, 0, 1, 1, 0, 0]
##  85/47 151/47 250/47 125/47 211/47 340/47 170/47 85/47
##
##  [1, 0, 1, 1, 0, 0, 1]
##  151/47 250/47 125/47 211/47 340/47 170/47 85/47 151/47

> because
> it usually takes me hours to get to what I want in the
> documentations :). I think I will use that, when i get it working in
> Ubuntu. Do you guys know of any pre-made package or guides for getting
> it working in Ubuntu?
>
> Well, I guess my idea was not as good as I thought it was :). But
> anyways... I look forward to Python 3.0 (Specially the
> __future__.with_statement and the standardization of names-- cStringIO
> is just too ugly for my eyes!)





More information about the Python-list mailing list