Velocity Reviews > Using fractions instead of floats

# Using fractions instead of floats

Nick Craig-Wood
Guest
Posts: n/a

 10-01-2007
Gabriel Genellina <(E-Mail Removed)> wrote:
> And gmpy: http://www.aleax.it/gmpy.html

And a concrete example

>>> from gmpy import mpq
>>> mpq(1,3)+mpq(0.4)

mpq(11,15)
>>> mpq(1,3)+mpq(4,10)

mpq(11,15)
>>> mpq(1,3)+mpq(6,10)

mpq(14,15)
>>> mpq(1,3)+0.6

mpq(14,15)
>>> mpq(5,2)

mpq(5,2)
>>> mpq(1,3)*mpq(6,10)*mpq(4,10)+mpq(7,

mpq(191,200)
>>>

--
Nick Craig-Wood <(E-Mail Removed)> -- http://www.craig-wood.com/nick

Stargaming
Guest
Posts: n/a

 10-01-2007
On Sun, 30 Sep 2007 20:10:05 -0700, Andres Riofrio wrote:

[snip]
>>From what I've read, seems that the principal reason for rejecting the

> PEP is that there was not much need (enthusiasm)... Well, then I have a
> question: Is there a way to make 5/2 return something other than an
> integer? I can do:
> class int(int):
> pass
> but that will only work if I do int(5)/int(2)...
>
> (setting __builtin__.int=int doesn't work, either)
>
> What I'd like is to be able to implement what I put in the proposal, as
> I don't think it's a really big language change...

[snip]

You could make up an example implementation by using fractionizing_int
(1) / fractionizing_int(3) (or whatever name you come up with).

I don't know of any particularly nice way to Just Let It Work anywhere in
python (perhaps some ugly byte code hacks, automatically wrapping ints).
So, you would have to implement it in C if you want to propose this for
CPython. And that's no 5 minute task, I guess.

Still, having this `int` behaviour working globally would include those
previously mentioned irrational numbers (but Pi is rational in any
visualization anyways, so FWIW that wouldn't be too much of a blockade).
But where would you put normal integer division then?
Introducing a new type seems best to me.

You could, as well, try to implement this in PyPy. If this would hit the
broad masses is another question, though.

Regards,
stargaming

Arnaud Delobelle
Guest
Posts: n/a

 10-01-2007
On Oct 1, 2:35 am, andresj <(E-Mail Removed)> wrote:

[snip Rational numbers in Python]

> I would like to get some feedback on this idea. Has this been posted
> before? If so, was it rejected? and for what?
> Also, I would like to know if you have improvements on the initial
> design, and if it would be appropiate to send it as a PEP.

As pointed out by others, implementations of rationals in Python
abound. Whereas there is a canonical representation of floats and ints
(and even longints) in the machine, it is not the case for rationals.
Moreover most programming tasks do not need rationals, so why burden
the language with them? If one needs them, there are perfectly
adequate modules to import (even though I, like many others I suspect,
have my own implementation in pure Python). Finally, arithmetic would
become very confusing if there were three distinct numeric types; it
already causes enough confusion with two!

--
Arnaud

Neil Cerutti
Guest
Posts: n/a

 10-01-2007
On 2007-10-01, Arnaud Delobelle <(E-Mail Removed)> wrote:
> Finally, arithmetic would become very confusing if there were
> three distinct numeric types; it already causes enough
> confusion with two!

Scheme says: It's not that bad.

--
Neil Cerutti
I am free of all prejudices. I hate everyone equally. --W. C. Fields

Arnaud Delobelle
Guest
Posts: n/a

 10-01-2007
On Oct 1, 6:26 pm, Neil Cerutti <(E-Mail Removed)> wrote:
> On 2007-10-01, Arnaud Delobelle <(E-Mail Removed)> wrote:
>
> > Finally, arithmetic would become very confusing if there were
> > three distinct numeric types; it already causes enough
> > confusion with two!

>
> Scheme says: It's not that bad.

Scheme has prefix numeric operators, so that 1/2 is unambiguously (for
the interpreter and the user) a litteral for 'the fraction 1/2'. You
can't avoid the confusion in python, as binary operators are infix. Of
course, we could create a new kind of litteral. Let's see, / and //
are already operators, so why not use /// ?

--
Arnaud

andresj
Guest
Posts: n/a

 10-02-2007

> > On 2007-10-01, Arnaud Delobelle <(E-Mail Removed)> 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, 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!)

richyjsm@gmail.com
Guest
Posts: n/a

 10-02-2007
On Oct 1, 8:30 am, Nick Craig-Wood <(E-Mail Removed)> wrote:
> >>> mpq(1,3)+0.6

> mpq(14,15)

Golly! That's quite impressive. And more than a little bit magic as
well, since 0.6 is definitely not the same as 3/5. How on earth does
this work?

Richard

mensanator@aol.com
Guest
Posts: n/a

 10-02-2007
On Oct 1, 7:09 pm, andresj <(E-Mail Removed)> wrote:
> > > On 2007-10-01, Arnaud Delobelle <(E-Mail Removed)> 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)
# 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!)

mensanator@aol.com
Guest
Posts: n/a

 10-02-2007
On Oct 1, 7:20 pm, (E-Mail Removed) wrote:
> On Oct 1, 8:30 am, Nick Craig-Wood <(E-Mail Removed)> wrote:
>
> > >>> mpq(1,3)+0.6

> > mpq(14,15)

>
> Golly! That's quite impressive. And more than a little bit magic as
> well, since 0.6 is definitely not the same as 3/5.

It's not? Since when?

>>> print gmpy.mpq('0.6')

3/5

> How on earth does this work?

The rationals are always reduced to lowest terms.

>
> Richard

richyjsm@gmail.com
Guest
Posts: n/a

 10-02-2007
On Oct 1, 9:03 pm, "(E-Mail Removed)" <(E-Mail Removed)> wrote:
> On Oct 1, 7:20 pm, (E-Mail Removed) wrote:
>
> > On Oct 1, 8:30 am, Nick Craig-Wood <(E-Mail Removed)> wrote:

>
> > > >>> mpq(1,3)+0.6
> > > mpq(14,15)

>
> > Golly! That's quite impressive. And more than a little bit magic as
> > well, since 0.6 is definitely not the same as 3/5.

>
> It's not? Since when?

The 0.6 above is a floating point number, mathematically very close to
0.6 but definitely not equal to it, since 0.6 can't be represented
exactly as a float.