Re: [BUG] Inconsistent float soustraction

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: [BUG] Inconsistent float soustraction

cedreek
> > Hi,

> >
> > I noticed in my image (damien last beta so 3.10 - windows XP and
> > Vista) that I have a strange bug when soustracting floats
> > successively. Here is how I reproduce it in a workspace:
> >
> > 1 - 0.2 -0.05 -0.3 = 0.45 "true"
> > 1 - 0.2 -0.05 -0.3 -0.1= 0.35  "true"
> > 1 - 0.2 -0.05 -0.3 -0.1 - 0.10= 0.25  "*****false*****"
> > 1 - 0.2 -0.05 -0.3 -0.1 - 0.10= 0.24999999999999995   true
> >
> > or again:
> > 1 - 0.1 = 0.9  true
> > 1 - 0.1 - 0.1 = 0.8 true
> > 1 - 0.1 - 0.1 - 0.1 = 0.7 false
> >
> >
> > Can somebody explain that or is it a bug ? I don't know yet if it's
> > specific to my image, so does other have the same behavior?
> > I can force the rounding of the result but find it strange.
> >
> > Cédrick
2008/2/17, danil osipchuk <[hidden email]>:
> This is not even squeak specific. Decimal floats not always can be
> represented precisely in binary form:
>
> http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
>


> Hi Cédrick,
>
>         if you need to operate with exact precision just don't trust floats. Use ScaledDecimals instead. In Squeak ScaledDecimals are implemented with the fraction so it's matematically stronger than floats. Use floats at presentation or user interface time and evade them at domain model.
>
>         cheers,
>
> Sebastian Sastre

uhm ok, good to know.
Actually, it was just a test that failed so I was surprised.

I still find the result odd.

Seeing ScaledDecimal>>testConvertFromFloat, I'm wandering if it would
be better to have Float>>=   considering egality if the difference is
less than 1.0e-9.

<primitive: 47>
aNumber isNumber ifFalse: [^ false].
^ (aNumber asFloat - self) abs  <  1.0e-9

I would prefer having = working as I expect, even if it would be wrong
for smaller values than 1.0e-9. For strict egality, == can be used.

Is it possible to disable a primitive call like here (it's optimized no ?) ?

Anyway, thanks for your answers.

Cédrick

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: [BUG] Inconsistent float soustraction

John Foster-3
Cedric,

Part of the issue is that different architectures will have different
values for machine epsilon (1e-09 in your post).  Machine epsilon is
defined to be the largest float such that

0.0 + epsilon = 0.0

Its value varies according to your machine though - typically a machine
with a much larger machine word size in its floating point processor will
have a much smaller machine epsilon. (The following is an example of a
Simple Lie, for an introduction to the Complicated Truth I suggest you get
hold of a book on Numerical Computation, which is an important study in
Computer Science).

Things are complicated further in that in any radix based number system
there are very simple numbers that cannot be written exactly.  In the
decimal number system any fraction with a denominator relatively prime to
the radix tends to be an infinitely repeating fraction. 1/3 or 3/7 are
examples.

Computers use binary numbers inside. 1/10 is not expressible as a
nonrecurring binary fraction, nor is 1/3, 3/10, 2/5 or 1/20.

Squeak does a good job of trying to promote numbers to ScaledDecimals, but
they are much more expensive to calculate than IEEE floats or Integers.

If we repeat your examples using Fractions we get

1 - (2/10) - (5/100) - ( 3/10) - (1/10) -(1/10) = (1/4) true

because Fractions are exact - in fact the definition of equality for
fractions is defined to be

( a/b ) = ( c/d ) if and only if ( a * d ) = (b * c)

which only uses Integer and BigNum arithmetic and allows arbitrary
precision (unless the numbers are so big you run out of memory).

Your idea of redefining equality for floats is a very bad idea because (1)
it assumes all hardware has the same value for machine epsilon and (2)
will break 50 years worth of programs that do numerical computation.

The simplest rule is any attempt to test floats (or doubles, or IEEE
decwords) for equality is a bug.  If there's a decimal point in your
calculations (or if there could be) then don't test for equality.  This is
taught to computing students at University in the first few weeks.  Any
work done by a Uni student who breaks this rule gets marked down very
severely!

I commend you on discovering this on your own by the way - it shows an
inquiring mind.  It's not everyone who hits one of the key issues in
Computer Science by themselves, and then thinks about it.

Yours,

John.

>> > Hi,
>> >
>> > I noticed in my image (damien last beta so 3.10 - windows XP and
>> > Vista) that I have a strange bug when soustracting floats
>> > successively. Here is how I reproduce it in a workspace:
>> >
>> > 1 - 0.2 -0.05 -0.3 = 0.45 "true"
>> > 1 - 0.2 -0.05 -0.3 -0.1= 0.35  "true"
>> > 1 - 0.2 -0.05 -0.3 -0.1 - 0.10= 0.25  "*****false*****"
>> > 1 - 0.2 -0.05 -0.3 -0.1 - 0.10= 0.24999999999999995   true
>> >
>> > or again:
>> > 1 - 0.1 = 0.9  true
>> > 1 - 0.1 - 0.1 = 0.8 true
>> > 1 - 0.1 - 0.1 - 0.1 = 0.7 false
>> >
>> >
>> > Can somebody explain that or is it a bug ? I don't know yet if it's
>> > specific to my image, so does other have the same behavior?
>> > I can force the rounding of the result but find it strange.
>> >
>> > Cédrick
>
> 2008/2/17, danil osipchuk <[hidden email]>:
>> This is not even squeak specific. Decimal floats not always can be
>> represented precisely in binary form:
>>
>> http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
>>
>
>
>> Hi Cédrick,
>>
>>         if you need to operate with exact precision just don't trust
>> floats. Use ScaledDecimals instead. In Squeak ScaledDecimals are
>> implemented with the fraction so it's matematically stronger
>> than floats. Use floats at presentation or user interface time
>> and evade them at domain model.
>>
>>         cheers,
>>
>> Sebastian Sastre
>
> uhm ok, good to know.
> Actually, it was just a test that failed so I was surprised.
>
> I still find the result odd.
>
> Seeing ScaledDecimal>>testConvertFromFloat, I'm wandering if it would
> be better to have Float>>=   considering egality if the difference is
> less than 1.0e-9.
>
> <primitive: 47>
> aNumber isNumber ifFalse: [^ false].
> ^ (aNumber asFloat - self) abs  <  1.0e-9
>
> I would prefer having = working as I expect, even if it would be wrong
> for smaller values than 1.0e-9. For strict egality, == can be used.
>
> Is it possible to disable a primitive call like here (it's optimized no ?)
> ?
>
> Anyway, thanks for your answers.
>
> Cédrick
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://lists.squeakfoundation.org/mailman/listinfo/beginners
>


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: [BUG] Inconsistent float soustraction

John Foster-3
Cedric,

As a follow up, when doing high precision arithmetic (in engineering,
numerical integration, weather prediction and the like) you usually have a
setup routine that does things like:

BEGIN
let a = 0.5
let b = a /2.0
while ( (a+b) <> a ) do
   epsilon = b
   b = b/2
endwhile

then epsilon is close to machine epsilon.

More sophisticated algorithms give more accurate values.

from that point we do indeed use ABS(a - b) < epsilon for 'close enough to
equal'.  There are a huge number of arithmetic tricks used to try to keep
the accumulated rounding errors within known bounds as well.

Some calculations are very badly behaved, and there is very little we can
do to try to keep results even remotely close to accurate.  Chaotic
systems are one class of problems that comes to mind (found in weather
prediction for example).  Another is inverting certain matrices - the
Vandemonde matrix is a classic example that is not singular, but you get
numbers that are less than machine epsilon so you find yourself trying to
divide by machine zero (or even worse get 0/0, known in computing as NaN ,
or NotANumber), even though it can be proved that these matrices do indeed
possess inverses.

I hope this makes you aware of how nasty floats and doubles (and quad and
decwords) are in computer arithmetic.  One book worth reading for a
(relatively) gentle introduction to this is "An Introduction to Numerical
Computations" by Yakowitz and Szidarovszky.  A more exhaustive treatment
can be found in "The Art of Computer Programming" by Donald Knuth, but
that is not a read for the light hearted.  "Programming Pearls" by Bentley
also has a few examples of how badly things can go awry if you neglect to
allow for the inherent failings of float arithmetic. The last book is
great reading for anyone interested in programming, and is an entertaining
and not too mind bending read.

I'm aware that this post is far more information than you asked for, but
is enough for you to get a real handle on this stuff if you want more
detail than "Never ever test floats for equality because it will bite you
on the arse big time, cost you your job, kill innocent people and cause
the collapse of banks, insurers and civilisation itself".

Enjoy,

John

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: [BUG] Inconsistent float soustraction

Marcin Tustin
In reply to this post by John Foster-3
I don't know which university you went to, but I certainly never observed any serious attempt to enforce such a rule at university. That said, it's a good one for all of us to learn if we don't apply it already.

On Feb 17, 2008 8:56 PM, <[hidden email]> wrote:
Cedric,

Part of the issue is that different architectures will have different
values for machine epsilon (1e-09 in your post).  Machine epsilon is
defined to be the largest float such that

0.0 + epsilon = 0.0

Its value varies according to your machine though - typically a machine
with a much larger machine word size in its floating point processor will
have a much smaller machine epsilon. (The following is an example of a
Simple Lie, for an introduction to the Complicated Truth I suggest you get
hold of a book on Numerical Computation, which is an important study in
Computer Science).

Things are complicated further in that in any radix based number system
there are very simple numbers that cannot be written exactly.  In the
decimal number system any fraction with a denominator relatively prime to
the radix tends to be an infinitely repeating fraction. 1/3 or 3/7 are
examples.

Computers use binary numbers inside. 1/10 is not expressible as a
nonrecurring binary fraction, nor is 1/3, 3/10, 2/5 or 1/20.

Squeak does a good job of trying to promote numbers to ScaledDecimals, but
they are much more expensive to calculate than IEEE floats or Integers.

If we repeat your examples using Fractions we get

1 - (2/10) - (5/100) - ( 3/10) - (1/10) -(1/10) = (1/4) true

because Fractions are exact - in fact the definition of equality for
fractions is defined to be

( a/b ) = ( c/d ) if and only if ( a * d ) = (b * c)

which only uses Integer and BigNum arithmetic and allows arbitrary
precision (unless the numbers are so big you run out of memory).

Your idea of redefining equality for floats is a very bad idea because (1)
it assumes all hardware has the same value for machine epsilon and (2)
will break 50 years worth of programs that do numerical computation.

The simplest rule is any attempt to test floats (or doubles, or IEEE
decwords) for equality is a bug.  If there's a decimal point in your
calculations (or if there could be) then don't test for equality.  This is
taught to computing students at University in the first few weeks.  Any
work done by a Uni student who breaks this rule gets marked down very
severely!

I commend you on discovering this on your own by the way - it shows an
inquiring mind.  It's not everyone who hits one of the key issues in
Computer Science by themselves, and then thinks about it.

Yours,

John.

>> > Hi,
>> >
>> > I noticed in my image (damien last beta so 3.10 - windows XP and
>> > Vista) that I have a strange bug when soustracting floats
>> > successively. Here is how I reproduce it in a workspace:
>> >
>> > 1 - 0.2 -0.05 -0.3 = 0.45 "true"
>> > 1 - 0.2 -0.05 -0.3 -0.1= 0.35  "true"
>> > 1 - 0.2 -0.05 -0.3 -0.1 - 0.10= 0.25  "*****false*****"
>> > 1 - 0.2 -0.05 -0.3 -0.1 - 0.10= 0.24999999999999995   true
>> >
>> > or again:
>> > 1 - 0.1 = 0.9  true
>> > 1 - 0.1 - 0.1 = 0.8 true
>> > 1 - 0.1 - 0.1 - 0.1 = 0.7 false
>> >
>> >
>> > Can somebody explain that or is it a bug ? I don't know yet if it's
>> > specific to my image, so does other have the same behavior?
>> > I can force the rounding of the result but find it strange.
>> >
>> > Cédrick
>
> 2008/2/17, danil osipchuk <[hidden email]>:
>> This is not even squeak specific. Decimal floats not always can be
>> represented precisely in binary form:
>>
>> http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
>>
>
>
>> Hi Cédrick,
>>
>>         if you need to operate with exact precision just don't trust
>> floats. Use ScaledDecimals instead. In Squeak ScaledDecimals are
>> implemented with the fraction so it's matematically stronger
>> than floats. Use floats at presentation or user interface time
>> and evade them at domain model.
>>
>>         cheers,
>>
>> Sebastian Sastre
>
> uhm ok, good to know.
> Actually, it was just a test that failed so I was surprised.
>
> I still find the result odd.
>
> Seeing ScaledDecimal>>testConvertFromFloat, I'm wandering if it would
> be better to have Float>>=   considering egality if the difference is
> less than 1.0e-9.
>
> <primitive: 47>
> aNumber isNumber ifFalse: [^ false].
> ^ (aNumber asFloat - self) abs  <  1.0e-9
>
> I would prefer having = working as I expect, even if it would be wrong
> for smaller values than 1.0e-9. For strict egality, == can be used.
>
> Is it possible to disable a primitive call like here (it's optimized no ?)
> ?
>
> Anyway, thanks for your answers.
>
> Cédrick
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://lists.squeakfoundation.org/mailman/listinfo/beginners
>


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: [BUG] Inconsistent float soustraction

cedreek
In reply to this post by John Foster-3
Thank you John,

Your interesting answer make me think that's true "there are no stupid
question" :)... I was bitten because, I finally decided to test-model
my code and was surprised by the failure I got, so I had a closer look
to what's happening in my model. I'm basically modeling a weight on
subsets of a set, so naturally 1 to 0 by 0.1... So it's not really a
problem in my case, anyway this small incursion in the Float world was
interesting. Today, I learn to things:
- I will avoide Float as much as possible :)
- Unit  Test are cool :)

>
> Part of the issue is that different architectures will have different
> values for machine epsilon (1e-09 in your post).  Machine epsilon is
> defined to be the largest float such that
>
> 0.0 + epsilon = 0.0

In Float, there is an class var named Epsilon (1.0e-12 in my image).
Method initialize in the class side of Float is interesting by the way...
So Epsilon := 0.000000000001.  "Defines precision of mathematical
functions" is set when the class is inittialized.

Just for information, is it possible to set this value at image
startup depending on the architecture ?

>
> Your idea of redefining equality for floats is a very bad idea because (1)
> it assumes all hardware has the same value for machine epsilon and (2)
> will break 50 years worth of programs that do numerical computation.
>
Oups so I'll avoid that :)

I just thought as = is different from ==, it might be "possible" to
redefine it so that 1 - 0.1 - 0.1 -0.1 = 0.7

Maybe the problem was not the "=" part, but how the 0.1 was evaluated.
When I type or enter "0.1", I mean a scaled decimal (fraction + scale)
but not a "float"... I expect that a precise value would result in a
precise one. Just thinking loud but couldn't 0.1 (maybe decimals
untill 0.0001) be evaluated as a precise value (as 1/3 evaluate as a
fraction) ?

It's probably becoming too pointless and I imagine Float are more
efficient so... Anyway, thanks again :)

Cédrick

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: [BUG] Inconsistent float soustraction

cedreek
In reply to this post by John Foster-3
> I'm aware that this post is far more information than you asked for, but
> is enough for you to get a real handle on this stuff if you want more
> detail than "Never ever test floats for equality because it will bite you
> on the arse big time, cost you your job, kill innocent people and cause
> the collapse of banks, insurers and civilisation itself".

It seems you anticipated some of my questions... (cross post)...

I'll avoid Floats :)

>
> Enjoy,
>


I really enjoyed and will read it again...

Cheers,

Cédrick

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: [BUG] Inconsistent float soustraction

cedreek
In reply to this post by cedreek
> In Float, there is an class var named Epsilon (1.0e-12 in my image).
> Method initialize in the class side of Float is interesting by the way...
> So Epsilon := 0.000000000001.  "Defines precision of mathematical
> functions" is set when the class is inittialized.
>
> Just for information, is it possible to set this value at image
> startup depending on the architecture ?

So ok we forget that... Perfectly explained :)
_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Re: [BUG] Inconsistent float soustraction (slightly offtopic)

John Foster-3
In reply to this post by Marcin Tustin
I studied and taught at Griffith University in Australia.  At the time the
computing dept was a weird combination of Business Programmers and
Numerical Modelers.  I wouldn't be surprised if this kind of fundamental
instruction has disappeared these days, given the tendency to expose
students to Java or C# as their 1st languages.  I believe this is going to
result in a lot of 'programmers' who are good at gluing pieces together,
but have little to no clue about memory or what actually goes on in
machines.

I guess I was lucky to have learned via the Pascal > C > Machine code >
Actor (an extinct Smalltalk dialect) > FORTRAN > C++ path.  I've seen
people who started with Java do terrible things, like seeding multiple
PRNGs based on system time rounded to the second inside tight loops, then
wondering why they have identical streams of PRNs.

My 2 cents,

John

> I don't know which university you went to, but I certainly never observed
> any serious attempt to enforce such a rule at university. That said, it's
> a
> good one for all of us to learn if we don't apply it already.
>
> On Feb 17, 2008 8:56 PM, <[hidden email]> wrote:
>
>> Cedric,
>>

<snip>

>> The simplest rule is any attempt to test floats (or doubles, or IEEE
>> decwords) for equality is a bug.  If there's a decimal point in your
>> calculations (or if there could be) then don't test for equality.  This
>> is
>> taught to computing students at University in the first few weeks.  Any
>> work done by a Uni student who breaks this rule gets marked down very
>> severely!
>>
>> I commend you on discovering this on your own by the way - it shows an
>> inquiring mind.  It's not everyone who hits one of the key issues in
>> Computer Science by themselves, and then thinks about it.
>>
>> Yours,
>>
>> John.
>>

<snip>

_______________________________________________
Beginners mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/beginners