Skip to content

arithmetic and logical operators

5 messages · Dave Mitchell, R. Michael Weylandt, Berend Hasselman +2 more

#
R FAQ 7.31 (Note, this isn't R specific, rather it's a problem with
the finitude of computers)

MW
On Wed, Jan 30, 2013 at 8:32 PM, Dave Mitchell <dmmtchll at gmail.com> wrote:
#
On 30-01-2013, at 21:32, Dave Mitchell <dmmtchll at gmail.com> wrote:

            
R-FAQ 7.31: http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-doesn_0027t-R-think-these-numbers-are-equal_003f

Berend
#
Because floating point arithmetic is done with a fixed
number of digits.   If you are working in base 10 and have
2 digits to work with you would have
   1/3 -> .33
   2/3 -> .67
so that
    1/3 + 1/3 < 2/3
You can index things with integers.  E.g., instead of storing 0.1, 0.05,
and 0.15, store  2, 1, and 3.  Do your comparisons on the integers
and multiply by 0.05 when you need to use them in that format.

You can work with numbers that are exactly representable with
52 binary digits, such as 1/1024 or 10^14+1/8.

You can work with smooth functions so the it doesn't matter
much what the sign of 0.15 - (0.10 + 0.05) is. 

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
#
On 30-Jan-2013 20:39:34 Berend Hasselman wrote:
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