On 19-Apr-05 Ralf Strobl wrote: > Dear List, > can anyone explain me this result (Windows XP, R 2.0.1): > > > (0.2-0.1)==0.1 > [1] TRUE > > (0.3-0.2)==0.1 > [1] FALSE > > Regards, > Ralf Strobl
It is a consequence of the finite length of the binary expression of decimal fractions, which is not exact except for multiples of 1/2, 1/4, 1/8, 1/16 ... (just as 1/3, 1/7 etc. are not exact in a decimal representation). Example (though this is not how floating-point is done, which is more complicated, and uses a different number of binary places to what R uses, but it illustrates the above point): 1/10 .0001100110011001100110011001100110 [to 34 binary places] 2/10 .0011001100110011001100110011001100 3/10 .0100110011001100110011001100110011 3/10 - 2/10: .0100110011001100110011001100110011 -.0011001100110011001100110011001100 ----------------------------------- =.0001100110011001100110011001100111 2/10 - 1/10 .0011001100110011001100110011001100 -.0001100110011001100110011001100110 ----------------------------------- =.0001100110011001100110011001100110 Not equal! The difference is 1 in the last place, i.e. 2^(-34) in this example. (2/10 - 1/10) is "right" (to the number of binary places calculated), while (3/10 - 2/10) is "wrong". (You might say that there's an inaccuracy in 2/10, since the truncation has chopped off subsequent digits 110011... which ought to round up the last digit of 2/10 to 1: but then you'll see that in the subtractions this changes the last digit of each result, so they're still different! This time, (3/10 - 2/10) would be "right", and (2/10 - 1/10) "wrong". In fact they're both wrong, all the time.) Now have a look at your cases in R: (0.3 - 0.2) - (0.2 - 0.1) ##[1] -2.775558e-17 2^(-55) ##[1] 2.775558e-17 which is the same phenomenon (though to a different number of binary places). You can't really escape from this entirely, though you can in R cover up such inconsistencies by using "all.equal": all.equal(base) Test if Two Objects are (Nearly) Equal Thus: all.equal((0.3 - 0.2),(0.2 - 0.1)) ##[1] TRUE which is fine if that's what you want to do. But then it may hide something that you might need to know: x<-1 ; y<-(x - 2^(-53)) all.equal(x,y) ##[1] TRUE x==y ##[1] FALSE Here you've deliberately made y different from x, but "all.equal" hides the truth, while "==" shows it. These tiny effects at the bottom end of the binary digits often do not matter and never show up in "ordinary" calculations, but on occasion they can lead to very delicate questions of precision. For instance, if you calculate two values x and y which might turn out to be slightly different (in the above way), yet for later logical decisions you don't want this to affect things, then you could do something like if(all.equal(x,y)){y <- x} which will make them identical, and for instance cause a later test "if(x==y)" to return "TRUE". But then should you have done {x <- y} instead? You have to think about whether or not this will matter! Hoping this helps, Ted. -------------------------------------------------------------------- E-Mail: (Ted Harding) <[EMAIL PROTECTED]> Fax-to-email: +44 (0)870 094 0861 Date: 19-Apr-05 Time: 10:43:08 ------------------------------ XFMail ------------------------------ ______________________________________________ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html