Beware: 2 is not always 2 in R

This post is minimalistic.
Consider this:

x <- 2.0000001

Now let's have look at what's inside x:

> [1] 2

But is it really true?

> [1] FALSE

Here you go.
A colleague of mine was once ruined by this for an entire day before we realized what was going on.
So, how to find out what REALLY is the value of x?

> [1] "2.0000001"
This entry was posted in R. Bookmark the permalink.

10 thoughts on “Beware: 2 is not always 2 in R

  1. Your technique won't work for the most common cases where the additional value is much smaller than the one you've added. If x <- 2 + 2e-15 then as.character() doesn't help at all and it still doesn't equal 2.

  2. Try this:

    x = .1 + .2
    as.character(.3) # ".3"
    as.character(x) # ".3"

    Yet the two numbers are not identical:

    x == .3 # FALSE

    To see why, try:

    formatC(x, digits=50)
    formatC(.3, digits=50)

    To properly compare the two numbers, round them to the required number of decimal places before comparing, e.g., round(x, 1) == .3. The function all.equal() may also be useful.

  3. Exactly - don't compare floating points, and if you want to see what the difference is between x and 2., just ask:

    x <- 2.0000001
    x # 2
    x-2 # 1e-07

  4. You do the R language a disservice by publishing this title. In *any* computing language or tool, you'll find both machine precision error limits and a difference between displayed digits and the stored value.

    • Hi, thanks to all of you for the comments.
      In reaction to this last one: I guess that it is good to know that this issue exists. I work with 5 other people who are using R, and none of them knew about it. Also, that is precisely why there are discussions below posts - to clarify things and to correct extreme opinions or titles. Cheers!

      • True. Well, there is all.equal() in R, and one can always write something like one of my toys:

        approxeq<-function(x,y,tolerance = .Machine$double.eps ^ 0.5,...) {
        #todo: input validation
        # I suppose I should allow length(x) == 1 and recyle...
        # or just change to a warning in case want to recycle shorter x, say
        if (length(x) != length(y)) warning('x,y lengths differ. Will recycle.')
        #don't care about dimensions so long as you're smart about inputs
        checkit <- abs(x-y) < tolerance

    • I see what you mean but believe the opposite: the "issue" documented here is actually a good example to learn and teach useful knowledge about how computers handle mathematics.

Leave a Reply

Your email address will not be published. Required fields are marked *