Velocity Reviews > Using fractions instead of floats

# Using fractions instead of floats

Terry Reedy
Guest
Posts: n/a

 10-02-2007

"andresj" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ps.com...
|| 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.

When you define your own class, you can make any operator (on instances of
that class) mean anything you want. But to use such methonds, once
defined, you first have to make instances of that class using
classname(init data) or whatever.

There is no way to hijack int op int though.

tjr

mensanator@aol.com
Guest
Posts: n/a

 10-02-2007
On Oct 1, 8:17?pm, (E-Mail Removed) wrote:
> 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.

Oh, you mean something like this, right?

>>> import gmpy
>>> a = 0.6
>>> a

0.59999999999999998

So, the rational should have 59999999999999998
in the neumerator and 100000000000000000 in the
denominator? But it doesn't

>>> b = gmpy.mpq(a)
>>> b

mpq(3,5)

Why do you suppose that is? For that matter, why
does

>>> str(a)

'0.6'

give me an EXACT representation? Didn't you just
say it couldn't be represented exactly?

Which is correct,

>>> str(a)

'0.6'

or

>>> repr(a)

'0.59999999999999998'

?

How does gmpy make the conversion from float to rational?

Rhamphoryncus
Guest
Posts: n/a

 10-02-2007
On Sep 30, 7:35 pm, andresj <(E-Mail Removed)> wrote:
> I was doing some programming in Python, and the idea came to my mind:
> using fractions instead of floats when doing 2/5.

The core problem with rationals (other than the inability to handle
irrationals) is their tendency to require more and more memory as
calculations progress. This means they get mysteriously slower and
slower.

http://mail.python.org/pipermail/pyt...er/166630.html

My own "pet numeric type" is fixed point. You get as much precision
as you specify. Alas, 2/5 would likely result in 0.

--

Robert Kern
Guest
Posts: n/a

 10-02-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Oct 1, 8:17?pm, (E-Mail Removed) wrote:
>> 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.

>
> Oh, you mean something like this, right?
>
>>>> import gmpy
>>>> a = 0.6
>>>> a

> 0.59999999999999998
>
> So, the rational should have 59999999999999998
> in the neumerator and 100000000000000000 in the
> denominator?

Actually (5404319552844595 / 2**53) would be best.

> But it doesn't
>
>>>> b = gmpy.mpq(a)
>>>> b

> mpq(3,5)
>
> Why do you suppose that is?

For the same reason that str() does. See below.

> For that matter, why
> does
>
>>>> str(a)

> '0.6'
>
> give me an EXACT representation?

It doesn't. It just rounds at a lower number of decimal places than is necessary
to faithfully represent the number. str() is intended to give friendly results,
not strictly correct ones. In this case it happens that float(str(0.6)) == 0.6,
but this is not guaranteed. For most numbers that a user or programmer might
enter, there will only be a relatively small amount of precision necessary, and
float(str(x)) == x will tend to hold. That's why it does this.

> Didn't you just
> say it couldn't be represented exactly?

Yup.

> Which is correct,
>
>>>> str(a)

> '0.6'
>
> or
>
>>>> repr(a)

> '0.59999999999999998'
>
> ?

The latter.

> How does gmpy make the conversion from float to rational?

gmpy has a configurable transformation between floats and the internal
representation. I believe the default goes through str().

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
an underlying truth."
-- Umberto Eco

Neil Cerutti
Guest
Posts: n/a

 10-02-2007
On 2007-10-01, Arnaud Delobelle <(E-Mail Removed)> wrote:
> 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 /// ?

But you wouldn't actually need a literal rational represention.

But I'm just playing Devil's Advocate here; I like rationals in
Scheme and Lisp, but I don't see a need for them in Python.

On the other hand, Python has had complex numbers a long time,
and it doesn't need those more than rationals, does it? My guess
is that it got complex numbers but not rationals because
rationals just aren't very efficient.

But as a programmer, I'm mostly just a data-twiddler, and don't
generally need either of those numeric type in my day-to-day
work. So I'm not the guy to ask.

--
Neil Cerutti
I'm tired of hearing about money, money, money, money, money. I just want to
play the game, drink Pepsi, wear Reebok. --Shaquille O'Neal

Arnaud Delobelle
Guest
Posts: n/a

 10-02-2007
On Oct 2, 12:42 pm, Neil Cerutti <(E-Mail Removed)> wrote:
> On 2007-10-01, Arnaud Delobelle <(E-Mail Removed)> wrote:
> > 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 /// ?

>
> But you wouldn't actually need a literal rational represention.

In which case rationals are better off in a module than in the
language!

> But I'm just playing Devil's Advocate here; I like rationals in
> Scheme and Lisp, but I don't see a need for them in Python.

> On the other hand, Python has had complex numbers a long time,
> and it doesn't need those more than rationals, does it? My guess
> is that it got complex numbers but not rationals because
> rationals just aren't very efficient.

Another guess could be that real numbers being closed under the four
arithmetic operations, there is no danger to accidentally step into
complex numbers. OTOH floats and rationals are two (conflicting) ways
of extending integers.

> But as a programmer, I'm mostly just a data-twiddler, and don't
> generally need either of those numeric type in my day-to-day
> work. So I'm not the guy to ask.

I use rationals a lot, and I don't want them in the language

--
Arnaud

Neil Cerutti
Guest
Posts: n/a

 10-02-2007
On 2007-10-02, Arnaud Delobelle <(E-Mail Removed)> wrote:
> On Oct 2, 12:42 pm, Neil Cerutti <(E-Mail Removed)> wrote:
>> On 2007-10-01, Arnaud Delobelle <(E-Mail Removed)> wrote:
>> > 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 /// ?

>>
>> But you wouldn't actually need a literal rational represention.

>
> In which case rationals are better off in a module than in the
> language!

I was supposing that 1/2 would result in a rational number, which
would require language support, whether it's a literal rational
number or a division of two integer constants.

>> But I'm just playing Devil's Advocate here; I like rationals
>> in Scheme and Lisp, but I don't see a need for them in Python.

>
>> On the other hand, Python has had complex numbers a long time,
>> and it doesn't need those more than rationals, does it? My
>> guess is that it got complex numbers but not rationals because
>> rationals just aren't very efficient.

>
> Another guess could be that real numbers being closed under the
> four arithmetic operations, there is no danger to accidentally
> step into complex numbers. OTOH floats and rationals are two
> (conflicting) ways of extending integers.

You would have to adopt a few simple conversion rules, a la
Scheme. Inexact numbers are contagious, for example. It was
pretty shocking for a Scheme programmer to see the gmpy package
break that rule.

> I use rationals a lot, and I don't want them in the language

Fair enough.

--
Neil Cerutti
The pastor will preach his farewell message, after which the choir will sing,
"Break Forth Into Joy." --Church Bulletin Blooper

mensanator@aol.com
Guest
Posts: n/a

 10-02-2007
On Oct 2, 1:12 am, Robert Kern <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > On Oct 1, 8:17?pm, (E-Mail Removed) wrote:
> >> 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.

>
> > Oh, you mean something like this, right?

>
> >>>> import gmpy
> >>>> a = 0.6
> >>>> a

> > 0.59999999999999998

>
> > So, the rational should have 59999999999999998
> > in the neumerator and 100000000000000000 in the
> > denominator?

>
> Actually (5404319552844595 / 2**53) would be best.
>
> > But it doesn't

>
> >>>> b = gmpy.mpq(a)
> >>>> b

> > mpq(3,5)

>
> > Why do you suppose that is?

>
> For the same reason that str() does. See below.
>
> > For that matter, why
> > does

>
> >>>> str(a)

> > '0.6'

>
> > give me an EXACT representation?

>
> It doesn't. It just rounds at a lower number of decimal places than is necessary
> to faithfully represent the number. str() is intended to give friendly results,
> not strictly correct ones. In this case it happens that float(str(0.6)) == 0.6,
> but this is not guaranteed. For most numbers that a user or programmer might
> enter, there will only be a relatively small amount of precision necessary, and
> float(str(x)) == x will tend to hold. That's why it does this.
>
> > Didn't you just
> > say it couldn't be represented exactly?

>
> Yup.
>
> > Which is correct,

>
> >>>> str(a)

> > '0.6'

>
> > or

>
> >>>> repr(a)

> > '0.59999999999999998'

>
> > ?

>
> The latter.
>
> > How does gmpy make the conversion from float to rational?

>
> gmpy has a configurable transformation between floats and the internal
> representation. I believe the default goes through str().

How do you do that? Is it configurable at run time or something that
has to be done when compiled?

But it is still wrong to say "0.6 is definitely not the same as 3/5".
One can say 0.6 doesn't have an exact float representation and that
inexact representation is not the same as 3/5. And I suppose one can
be surprised that when this inexact representation is coerced to a
rational the result is now exact.

Would that be a fairer way of putting it?

>
> --
> Robert Kern
>
> "I have come to believe that the whole world is an enigma, a harmless enigma
> that is made terrible by our own mad attempt to interpret it as though it had
> an underlying truth."
> -- Umberto Eco

richyjsm@gmail.com
Guest
Posts: n/a

 10-02-2007
On Oct 2, 5:27 pm, "(E-Mail Removed)" <(E-Mail Removed)> wrote:
> But it is still wrong to say "0.6 is definitely not the same as 3/5".

Out of context, I'd certainly agree. But from the context, I assumed
it was clear that the 0.6 was a Python float. I probably should have
made this clearer. My statement should probably have been something
like: a literal 0.6 in Python code does not have the same mathematical
value as the rational (or real) number 3/5.

Richard

mensanator@aol.com
Guest
Posts: n/a

 10-02-2007
On Oct 2, 5:43 pm, (E-Mail Removed) wrote:
> On Oct 2, 5:27 pm, "(E-Mail Removed)" <(E-Mail Removed)> wrote:
>
> > But it is still wrong to say "0.6 is definitely not the same as 3/5".

>
> Out of context, I'd certainly agree. But from the context, I assumed
> it was clear that the 0.6 was a Python float. I probably should have
> made this clearer. My statement should probably have been something
> like: a literal 0.6 in Python code does not have the same mathematical
> value as the rational (or real) number 3/5.

Ok, so maybe I should have said: the literal 0.6 isn't what gets added
to mpq(1,3) to form the sum. What actually is added is the 0.6 coerced
to an mpq which is then added to mpq(1,3). So what 0.6 is as a float
is
relevent only to what it gets coerced to.

>
> Richard