[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