[R] arithmetic and logical operators
(Ted Harding)
Ted.Harding at wlandres.net
Thu Jan 31 00:22:56 CET 2013
On 30-Jan-2013 20:39:34 Berend Hasselman wrote:
>
> On 30-01-2013, at 21:32, Dave Mitchell <dmmtchll at gmail.com> wrote:
>
>> Why, in R, does (0.1 + 0.05) > 0.15 evaluate to True? What am I missing
>> here? How can I ensure this (ostensibly incorrect) behavior doesn't
>> introduce bugs into my code? Thanks for your time.
>>
>
> R-FAQ 7.31:
> http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-num
> bers-are-equal_003f
>
> Berend
And, to put Dave's specific query into the context of that FAQ:
(0.1 + 0.05) > 0.15
# [1] TRUE
(0.1 + 0.05) - 0.15
# [1] 2.775558e-17
so that tiny 2.775558e-17 is the inexactitude (due to finite
binary representation).
As an interesting variant:
(1.0 + 0.5) > 1.5
# [1] FALSE
(1.0 + 0.5) - 1.5
# [1] 0
and that is because 1.0 and 0.5, and also 1.5, have exact finite
binary representations, e.g.:
1.0 == 1.0000000000000000
0.5 == 0.1000000000000000
1.5 == 1.1000000000000000
whereas 0.1, 0.5 and 0.15 are these numbers divided by 10 = 2*5;
and while you can exactly do the "/2" part (just shift right by
one binary place), you can't exactly divide by 5 in finite binary
arithmetic (any more than you can exactly divide by 3 in decimal),
because 5 is not a factor of the base (2) of the binary representation
(whereas, in decimal, both 2 and 5 are factors of 10; but 3 isn't).
Whereas R has the function all.equal() to give the "right" answer
for most things like
(0.1 + 0.05) == 0.15
# [1] FALSE
all.equal((0.1 + 0.05), 0.15)
# [1] TRUE
(because it tests for equality to within a very small tolerance,
by default the square root of the binary precision of a double
precision binary real number), R does not have a straightforward
method for testing the truth of "(0.1 + 0.05) > 0.15" (and that
is because the question is not clearly discernible from the
expression, when imprecision underlies it).
You could emulate all.equal() on the lines of
(0.1 + 0.05) > (0.15 + .Machine$double.eps^0.5)
# [1] FALSE
(0.1 + 0.05) < (0.15 - .Machine$double.eps^0.5)
# [1] FALSE
(or similar). Observe that
.Machine$double.eps^0.5
# [1] 1.490116e-08
.Machine$double.eps
# [1] 2.220446e-16
(0.1 + 0.05) - 0.15
# [1] 2.775558e-17
Hoping this helps,
Ted.
-------------------------------------------------
E-Mail: (Ted Harding) <Ted.Harding at wlandres.net>
Date: 30-Jan-2013 Time: 23:22:53
This message was sent by XFMail
More information about the R-help
mailing list