1

If I type:

x<-seq(0,20,.05)
x[30]
x[30]==1.45

Why do I obtain a False from the last line of code? What did I do wrong here?

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Simon
  • 1,942
  • 5
  • 18
  • 22
  • 2
    x[30] is `14.5` not `1.45`. I dint down-vote, but I think you should delete this question. – Arun May 01 '13 at 19:30
  • Yes I made a typo in my question I have now corrected. You should read x<-seq(0,20,.05) – Simon May 01 '13 at 19:32
  • This is due to [**floating point inaccuracy**](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). Do this: `x <- seq(0, 20, 0.5); sprintf("%.20f", x[30])` and now this: `x <- seq(0, 20, 0.05); sprintf("%.20f", x[30])`. – Arun May 01 '13 at 19:34

2 Answers2

5

This question has been asked a million times, albeit in different forms. This is due to floating point inaccuracy. Also here's another link on floating point errors you may want to catch up on!

Try this to first see what's going on:

x <- seq(0, 20, 0.5)
sprintf("%.20f", x[30]) # convert value to string with 20 decimal places
# [1] "14.50000000000000000000"
x[30] == 14.5
# [1] TRUE

All is well so far. Now, try this:

x <- seq(0, 20, 0.05)
sprintf("%.20f", x[30]) # convert value to string with 20 decimal places
# [1] "1.45000000000000017764"
x[30] == 1.45
# [1] FALSE

You can see that the machine is able to accurately represent this number only up to certain digits. Here, up to 15 digits or so. So, by directly comparing the results, you get of course a FALSE. Instead what you could do is to use all.equal which has a parameter for tolerance which equals .Machine$double.eps ^ 0.5. On my machine this evaluates to 1.490116e-08. This means if the absolute difference between the numbers x[30] and 1.45... is < this threshold, then all.equal evaluates this to TRUE.

all.equal(x[30], 1.45)
[1] TRUE

Another way of doing this is to explicitly check with a specific threshold (as @eddi's answer shows it).

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Ricardo Saporta
  • 54,400
  • 17
  • 144
  • 178
3

This has to do with the fact that these are double's, and the correct way of comparing double's in any language is to do something like:

abs(x[30] - 1.45) < 1e-8   # or whatever precision you think is appropriate
Nimantha
  • 6,405
  • 6
  • 28
  • 69
eddi
  • 49,088
  • 6
  • 104
  • 155