Re: for problem...

From: Robert Heller (heller_at_deepsoft.com)
Date: 11/29/03


Date: Sat, 29 Nov 2003 22:03:44 +0000


  David Cobac <david.cobacNOSPAM@invalid.free.fr>,
  In a message on 29 Nov 2003 18:13:01 +0100, wrote :

DC> Robert Heller <heller@deepsoft.com> a écrit :
DC> >Removing the braces (in this case) should not make any difference. The
DC> >braces don't have anything to do with the problem at hand. I suspect
DC> >that the 'someone in fr.comp.lang.tcl' is using a different processor
DC> >(with a different FPU) or something.
DC>
DC> Ah...i've tried it and :
DC>
DC> (david) 101 % for {set k 0} {$k<=1} {set k [expr $k+0.01]} {puts $k}
DC> 0
DC> 0.01
DC> ...
DC> 0.98
DC> 0.99
DC> 1.0
DC> (david) 101 % for {set k 0} {$k<=1} {set k [expr {$k+0.01}]} {puts $k}
DC> 0
DC> 0.01
DC> ...
DC> 0.98
DC> 0.99

I'm guessing it is in the details of when the byte compiler does its
thing and when it binds the variables and constants as floating point
numbers and expressions. This causes a small difference in the amount
of roundoff error that shows up. The error is small, but accumulates
and effects the final results in an inconsistent manor.

Try these two:

for {set k 0} {$k<=1} {set k [expr $k+0.01]} {puts [format %20.18lf $k]}

and

for {set k 0} {$k<=1} {set k [expr {$k+0.01}]} {puts [format %20.18lf $k]}

For a clue about what is happening off in roundoff land.

An important thing to notice is that k is NOT going from 0 to 1.0 by
exactly 0.01, but is actually has a 'slightly' different increment,
since '0.01' is never an exact value. This error shows up when you
format the results with a large number of digits of precision. This is
in the *nature* of floating point operations. For an operation like
this, floating point ops are notoriously suspect and create these sorts
of problems and should be avoided. Writing the loop as:

for {set ik 0} {$ik <= 100} {incr ik} {
  set k1 [expr {double($ik) * .01}]
  set k2 [expr double($ik) * .01]
  puts [format {with braces: %20.18lf, without braces: %20.18lf} $k1 $k2]
}

will always give consistent results, with the roundoff error 'contained'
in a predictable fashion. This is because the increment is an integer
and is *exact*. The imprecision is introduced at the last possible
moment in the code. The longer you can defer this imprecision and/or
roundoff error the more accurate and 'correct' your results will be.

It is a very important programming lesson to understand the nature and
*limitations* of floating point operations. Floating point operations
are almost never *exact* -- that is never the point. Floating point
numbers are used when the *range* of the values exceeds the range
possible with integer (fixed point) numbers *AND* exact precision can
be traded off. It is generally always better to use integers (possibly
scaled), when the range is limited and an exact result is needed. Some
languages (such as Common Lisp) have an indefinite precision integers
(bignums). Common Lisp also has 'rational numbers', which are stored
as pairs of numbers, such as 1,3 for 1/3, which allows a way to exactly
represent fractions, without the problems you are seeing. I don't know
if there is a Tcl extension that implements 'bignums' or 'rational
numbers'. Generally, in specific cases one can program around the
imprecision of floating point numbers. In the specific case you are
using, the range of the numbers (0.0 through 1.0 by .01) is small
(exactly 101 values), so neither bignums nor floating point numbers are
actually needed. Using integers here makes sense and gives the most
exact results.

DC>
DC> --
DC> cordialement
DC> david cobac
DC>

                                     \/
Robert Heller ||InterNet: heller@cs.umass.edu
http://vis-www.cs.umass.edu/~heller || heller@deepsoft.com
http://www.deepsoft.com /\FidoNet: 1:321/153

                                 



Relevant Pages

  • Re: Weird find function error
    ... Simple floating point roundoff error. ... represented exactly as a double, and the exact value your computer ... onwards. ...
    (comp.soft-sys.matlab)
  • Re: Error: PHP math operation
    ... Here is the O/P.. ... My bet is that 55-55 would come out exact. ... Now you have 2.2 which is in floating point time 25 which is integer. ... There is an inevitable roundoff error. ...
    (comp.lang.php)
  • Re: Float comparison
    ... Oh, it exists, but not in that floating representation. ... Keith has already mentioned the need to do an error analysis if you want to know what the possible error. ... I know of code which carefully uses doubles to do integer arithmetic, staying within the range where integers can be represented exactly, in order to use the greater range of exact integral values that a double can represent on that specific implementation than an int. ... So either integer types cannot store exact values and you need to do a full error analysis to determine the range of values they might represent or floating point variables can store exact values which are exactly the mathematically correct values the program is intended to store. ...
    (comp.lang.c)
  • Re: Cant get Access to run a query with a time field
    ... Since the user enters an exact value, why isn't it saved to the ... Second, a date time value is a floating point value, ... >> Vanderghast, Access MVP ...
    (microsoft.public.access.queries)
  • Re: Wrong results when comparing negative double variables in an if statement
    ... debugging purposes, not because floating-point numbers have hundreds ... >The output as copied from the emulated DOS window is: ... There is no exact value of 0.001 in binary floating point, ...
    (comp.lang.c)