Re: Precision issue

From: Stephen Horne ($$$$$$$$$$$$$$$$$_at_$$$$$$$$$$$$$$$$$$$$.co.uk)
Date: 10/10/03


Date: Fri, 10 Oct 2003 15:14:52 +0100

On 10 Oct 2003 22:38:22 +0950, Ben Finney
<bignose-hates-spam@and-benfinney-does-too.id.au> wrote:

>On Fri, 10 Oct 2003 10:36:16 +0000 (UTC), Duncan Booth wrote:
>> I know this is an FAQ, but the one thing I've never seen explained
>> satisfactorily is why repr(3.4) has to be '3.3999999999999999' rather
>> than '3.4'?
>
>Because '3.4' is what str(3.4) returns. If repr(3.4) lies about the
>value stored, what function will you leave us to discover the actual
>value?
>
>The str() function is for getting the working output of the value. The
>repr() function is for discovering, as precisely as possible, the actual
>value.

Is there a basis for that claim?

My impression has always been that 'repr' gives a representation of
the value which, when parsed (using 'eval', for instance),
reconstructs the original value. In this respect, '3.4' is just as
good as '3.3999999999'.

IIRC, a binary float can always be given a precise decimal
representation - it simply tends to take a lot of digits. The fact
that repr doesn't give a perfect representation of the binary float
value suggests that it is not 'for discovering, as precisely as
possible, the actual value'.

Out of curiosity, I wrote the function at the bottem of this post to
convert a Python float into two string representations - a rational
and a decimal - both having precisely the same value as the float. I
got the following results starting with 3.4...

Rational : 7656119366529843/2251799813685248
Decimal : 3.399999999999999911182158029987476766109466552734375

I don't guarantee that the code is bug free - it may well be very
fragile, depending on platform specific float handling - but I believe
these results are accurate. For the record, I'm running Python 2.3
under Windows 2000 on a Pentium 4.

I am not aware of a Python standard function which will give this
rather impractical level of precision. But if Pythons repr function
was intended 'for discovering, as precisely as possible, the actual
value', it really should give the decimal value from above which it is
clearly possible to discover. The truth is, however, that such
discovery is rarely if ever useful - floats are inherently approximate
values.

Converting float values to decimal is almost always either for the
benefit of human readers, or for creating text representations that
will be converted back to floats at some point. str serves the first
purpose well. For the second, the important identity is that
eval(repr(x)) == x (or at least a sufficiently close approximation -
I'm not sure if repr currently preserves the full precision of the
float).

Here's the code...

def perfect (val) :
  # Convert to rational
  
  num = 0
  denom = 1
  
  # handle integer part
  
  num = int(val)
  val -= num
  
  # handle fractional part
  
  while val != 0 :
    val *= 2
    num *= 2
    denom *= 2
  
    if val >= 1 :
      num += 1
      val -= 1

  rat = str(num)+"/"+str(denom)
  
  # convert to decimal form
  
  dec = str(num/denom) + "."
  num = num % denom
  
  while num > 0 :
    num *= 10
    dec += str(num / denom)
    num = num % denom

  return (rat, dec)

-- 
Steve Horne
steve at ninereeds dot fsnet dot co dot uk


Relevant Pages

  • Re: Losing Precision from FLOAT in DBD::Informix
    ... The versions of CSDK and IDS are also not ... STSM, Informix Database Engineering, IBM Data Management ... >> are declared FLOAT. ... >> - where and why is the precision lost? ...
    (perl.dbi.users)
  • Re: converting float to double
    ... >> insists that I read the stock prices as float. ... >> Since everywhere else the system uses double to hold these prices, ... A 64 bit integer will correctly model currency to 18 digits (with ... calcuations in 110 digits of precision (so that things like interest ...
    (comp.lang.c)
  • Re: one-liner for characater replacement
    ... (previous snip, someone wrote) ... integer divide as a coefficient of a float polynomial. ... They consider magnitude, but not precision, so int to float is ...
    (comp.lang.fortran)
  • Re: How about adding rational fraction to Python?
    ... which is a narrower class than Num but it could still be Float, Double, ... a list of fractionals. ... thing" for ints. ...
    (comp.lang.python)
  • RE: Losing Precision from FLOAT in DBD::Informix
    ... Subject: Losing Precision from FLOAT in DBD::Informix ... An SQL FLOAT in Informix is equivalent to a C double. ... The alternative way to work it is to modify the switch so that the SQLFLOAT ... You may need to choose a different format for the value than ...
    (perl.dbi.users)