> > Hi,
2008/2/17, danil osipchuk <[hidden email]>:
> > > > 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 > 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 |
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 |
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 |
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, _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
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 |
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 |
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 |
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 |
Free forum by Nabble | Edit this page |