Using fractions instead of floats

Robert Kern robert.kern at gmail.com
Tue Oct 2 19:26:59 EDT 2007


mensanator at aol.com wrote:
> On Oct 2, 1:12 am, Robert Kern <robert.k... at gmail.com> wrote:
>> mensana... at aol.com wrote:

>>> 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?

Run-time. Use gmpy.set_fcoform(). There is documentation:

  http://gmpy.googlecode.com/svn/trunk/doc/gmpydoc.txt

However, it appears I was wrong about the default. The default will simply
extract the C double and call mpf_set_d() on it to convert it to the appropriate
internal mpf format. This faithfully gives:

In [26]: gmpy.mpf(0.6)
Out[26]: mpf('5.9999999999999998e-1')

The real conversion to mpq rational numbers takes place in using gmpy.f2q():

In [28]: gmpy.f2q?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
Namespace:      Interactive
Docstring:
    f2q(x[,err]): returns the 'best' mpq approximating x to
    within relative error err (default, x's precision); 'best'
    rationals as per Stern-Brocot tree; mpz if denom is 1.
    If err<0, error sought is 2.0 ** err.

In [44]: d = gmpy.mpf(0.6)

In [45]: d
Out[45]: mpf('5.9999999999999998e-1')

In [46]: d.getrprec()
Out[46]: 53

In [47]: gmpy.f2q(d)
Out[47]: mpq(3,5)

In [48]: gmpy.f2q(d, -53)
Out[48]: mpq(3,5)

In [49]: gmpy.f2q(d, -54)
Out[49]: mpq(3,5)

In [50]: gmpy.f2q(d, -55)
Out[50]: mpq(6002194384070353L,10003657306783922L)


The procedure followed here finds mpq(3,5) because evaluating "3.0/5.0" in as
binary floating point numbers in double precision gives you the same thing as
evaluating "0.6". So mpq(3,5) is the most parsimonious rational number
*approximating* Python's float("0.6") to within the default double-precision of
binary floating point arithmetic. However, float("0.6") is a rational number
that has the precise value of mpq(6002194384070353L,10003657306783922L).

> But it is still wrong to say "0.6 is definitely not the same as 3/5".

In the context in which it was said, I don't think it's wrong though it is
incomplete and confusing if taken out of that context.

> 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?

Yes.

-- 
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




More information about the Python-list mailing list