This post is minimalistic.

Consider this:

x <- 2.0000001

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

x > [1] 2

But is it really true?

x==2 > [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?

Try:

as.character(x) > [1] "2.0000001"

...alternatively, have a look at ?options / digits.

Agree, check your output settings. Also don't compare floating point numbers directly. http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

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.

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.

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

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

return(invisible(checkit))

}

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.

I am always nervous about floating-point equality, but am amazed at how often it works in R.