[squeakdev] Re: The joys (or not) of floating point numbers
Nicolas Cellier
nicolas.cellier.aka.nice at gmail.com
Tue Mar 26 09:37:52 UTC 2013
2013/3/26 glenpaling <slp5591 at me.com>:
> tim Rowledge wrote
>> As a sideeffect of running the SpaceTally code I had to look at
>> implementations of #roundTo: because the output was bizarrely formatted.
>>
>> It turns out that for several of the percentage values calculated by 
>> percent := s spaceForInstances*100.0/totalInstSpace roundTo: 0.1.
>>  we get decidedly not numbers that match what we probably think we should
>> get. For example
>> 28846801 *100.0 / 53172599 > 54.25125260474855
>> BUT
>> 54.25125260474855 roundTo: 0.1 > 54.300000000000004
>> What? That's not even correct, let alone rounded to the requested
>> precision.
>>
>> Who is a numerics aficionado?
>>
>> tim
>> 
>> tim Rowledge;
>
>> tim@
>
>> ; http://www.rowledge.org/tim
>> Managing programmers is like herding cats.
>
> roundTo: rounds to a quantum so:
>
> 100 roundTo: 8 > 104
> 100 roundTo: 0.8 > 100
> 100 roundTo: (Float pi) > 100.53096491487338
>
> For printing you want:
> 54.25125260474855 printShowingDecimalPlaces: 1 > '54.3'
>
>
Yep, it's because we now tell the awfull truth about floats.
0.1 = (1/10) > false. "it's not exactly 1/10"
0.1 = (1/10.0) > true. "yes, it's the same approximation, with same
rounding error"
#(successor predecessor) allSatisfy: [:neighbourhood 
((0.1 perform: neighbourhood) asFraction  (1/10)) abs >= (0.1
asFraction  (1/10)) abs]. "yes 0.1 is closest float to 1/10"
(0.1 asFraction  (1/10)) / 0.1 ulp > 0.4. "Yep, 0.4 ulp error is OK,
IEEE 754 ops guaranty +/ 0.5 ulp"
but:
543/10.0 > 54.3. "sounds good"
543/10.0 = (543/10) > false. "But inexact, with a single rounding error"
543*0.1> 54.300000000000004. "this cumulated two rounding errors"
(54.3 asFraction (543/10)) / 54.3 ulp > 0.4.
((543*0.1) asFraction (543/10)) / 54.3 ulp > 0.6.
So what you want is 543/10, but that's not what roundTo: 0.1 does...
Old 3.X Squeak could maintain the illusion a little longer because it
used to print Floats approximately.
Float>>printString now prints the shortest decimal form that will be
reinterpreted as the same Float, and that's the only thing that
changed.
Every two finite different Float shall have a different print.
Use printShowingDecimalPlaces: as suggested
or round to an exact fraction
54.25125260474855 roundTo: 1/10.
54.25125260474855 roundTo: 0.1s1.
Nicolas
>
> 
> View this message in context: http://forum.world.st/Thejoysornotoffloatingpointnumberstp4678288p4678289.html
> Sent from the Squeak  Dev mailing list archive at Nabble.com.
>
More information about the Squeakdev
mailing list
