This question already has answers here:
Why are these numbers not equal?
(6 answers)
Closed 9 years ago.
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?
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).
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
Related
I'm having a numeric issue using qnorm(psn()). The problem is numeric.
Firstly, the Skew-Normal CDF round the result, since psn(9) is not 1:
library(sn)
psn(9)
#[1] 1
then
qnorm(psn(9))
#[1] Inf
And see that:
qnorm(.9999999999999999)
#[1] 8.209536
qnorm(.99999999999999999)
#[1] Inf
note that 8.209536 is not that big, so this rounding is very imprecise.
Then, my final problem is the calculation of qnorm(psn()), that is part of my Copula density. Any hint on how can I avoid these numerical problems?
(This is not a resolution to your dilemma, more of an explanation of why I think you're seeing this and perhaps not likely to find an easy solution.)
I think this is getting into the realm where normal floating-point precision isn't going to work for you. For instance, doing the inverse of your function:
options(digits=22)
pnorm(8.209536)
# [1] 0.99999999999999989
pnorm(8.209536) - 1
# [1] -1.1102230246251565e-16
which is very close to
.Machine$double.eps
# [1] 2.2204460492503131e-16
which, according to ?.Machine, is
double.eps: the smallest positive floating-point number 'x' such that
'1 + x != 1'. It equals 'double.base ^ ulp.digits' if either
'double.base' is 2 or 'double.rounding' is 0; otherwise, it
is '(double.base ^ double.ulp.digits) / 2'. Normally
'2.220446e-16'.
It might be possible to translate what you need into higher-precision using auxiliary packages like gmp or Rmpfr. (I don't know if they support qnorm-like operations.)
This question already has answers here:
Why are these numbers not equal?
(6 answers)
Closed 2 years ago.
I came across a strange thing in R programming. When I simulate a sequence and want to judge whether the element is less than 0.5,
t=(1:1440)/1440
x=(t[720]-t[648])/0.1
x
#output:[1] 0.5
x<1/2
#output:[1] TRUE
x=0.5
x<1/2
#output:[1] FALSE
The two results are completely opposite and obviously the second result is what I want. Can anybody help me?
Floating point arithmetic is not exact in R, and the value you expect to be numerically exact to 0.5 may in fact be slightly more (or less). One possible workaround here would be to use rounding:
t <- (1:1440)/1440
x <- (t[720]-t[648]) / 0.1
round(x, 1) < 0.5
This question already has answers here:
Why are these numbers not equal?
(6 answers)
Closed 5 years ago.
Why does only A out of A and B below equal 29? What is different about using a calculation as the x argument?
#A
floor(x = (1.45/0.05))
#B
floor(x = 29)
> #A
> floor(x = (1.45/0.05))
[1] 28
> #B
> floor(x = 29)
[1] 29
Like #bouncyball indicated it is a floating point problem.
If you go for example to this link and enter 1.45 or 0.05 you will notice that their binary representations are "infinitely" long (i.e. you can't write 1.45 with a finite string in binary).
Because your PC doesn't have infinite storage to store the digit he "chops" it off at some point - meaning he basically has your 1.45 as something like 1.49999999999 (nevermind the number of 9s) in his system. The same happens for 0.05.
Now your computer internally gets something like 28.9999999999999 - but he's not stupid when he outputs it. He knows, well 28.9999999999 is probably supposed to be 29 - so when he outputs it he just rounds. Except when you tell him explicitly to round using "floor" - then he rounds 28.99999999 to 28.
Hope that makes sense.
This question already has answers here:
Why are these numbers not equal?
(6 answers)
Closed 8 years ago.
Does the last statement in this series of statements make logical sense to anybody else? R seems to give similar results for a small subset of possible sums of decimals under 1. I cannot recall any basic mathematical principles that would make this true, but it seems to be unlikely to be an error.
> 0.4+0.6
[1] 1
> 0.4+0.6==1.0
[1] TRUE
> 0.3+0.6
[1] 0.9
> 0.3+0.6==0.9
[1] FALSE
Try typing 0.3+0.6-0.9, on my system the result is -1.110223e-16 this is because the computer doesn't actually sum them as decimal numbers, it stores binary approximations, and sums those. And none of those numbers can be exactly represented in binary, so there is a small amount of error present in the calculations, and apparently it's small enough not to matter in the first one, but not the second.
Floating point arithmetic is not exact, but the == operator is. Use all.equal to compare two floating point values in R.
isTRUE(all.equal(0.3+0.6, 0.9))
You can also define a tolerance when calling all.equals.
isTRUE(all.equal(0.3+0.6, 0.9, tolerance = 0.001))
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Numeric comparison difficulty in R
Hello All,
According to "R Inferno" paper. I'm right now in the first circle of R hell. This is where pagans expect 0.1 == 0.3/3. Paper recommends using all.equal function for such cases, however I need to check ">=" or "<=" conditions. With current example on of them fail:
> .1 >= .3/3
[1] TRUE
> .1 <= .3/3
[1] FALSE
Is there a similar function to all.equal that checks inequalities?
Thank you,
Ilya
The main test of all.equal is whether abs(x-y) < tolerance for some values x and y and some small tolerance. Equivalent inequality tests would check:
x <= y: x-y < tolerance
x < y: x-y < -tolerance
x >= y: x-y > -tolerance
x > y: x-y > tolerance
See these questions:
In R, what is the difference between these two?
Numeric comparison difficulty in R
Generally speaking, you can deal with this by including a tolerance level as per the second link above.
Please see the R FAQ entry Why doesn't R think these numbers are equal and the references therein.
You could try judicious use of zapsmall() which seems to give the behavior you are looking for. I don't know if this works in all situations. e.g.,
.1 >= zapsmall(.3/3)
[1] TRUE
> .1 <= zapsmall(.3/3)
[1] TRUE