First circle of R hell. 0.1 != 0.3/3 [duplicate] - r

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

Related

How to deal with underflow in R? [duplicate]

This question already has answers here:
Dealing with very small numbers in R
(4 answers)
Closed 1 year ago.
I want to compute this number :
0.34911191 ^ 1157
I am using R programming language and it returns me 0 (this is an underflow problem). How I can fix it? Thanks.
Are you looking for something like this?
The CRAN package Brobdingnag has two vignettes explaining its use.
library(Brobdingnag)
x <- 1157 * log(0.34911191)
y <- as.brob(x)
exp(y)
#[1] +exp(-1217.6)
exp(y) < .Machine$double.neg.eps
#[1] TRUE
You can test the result using the Numerical Characteristics of the Machine (.Machine {base}), as shown below:
> 0.34911191 ^ 10 < .Machine$double.neg.eps
[1] FALSE
> 0.34911191 ^ 1157 < .Machine$double.neg.eps
[1] TRUE
double.neg.eps is a small positive floating-point number x such that 1 - x != 1.

Numerical problems with qnorm

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.)

Logic regarding summation of decimals [duplicate]

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))

Why did I obtain wrong answer when using "=="? [duplicate]

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

Unexpected behaviour of greater and less than [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why are these numbers not equal?
Can anyone explain to me, why R answers FALSE in the following case?
(1-0.9)>=0.1
How can I get TRUE for comparisons of that kind?
This has to do with floating point precision. There is in essence an infinite amount of floating points, do representing them in the computer can only be done discretely, and thus with limited precision. To take this limited precision into account, use all.equal to make the comparison. As #RomainFracois said, this is very frequently asked question in R.
This is the classic R FAQ 7.31. You need all.equal
You could create your own binary operators to do what you're after and store them in your .Rprofile:
`%>=%` <- function(x, y) all.equal(x, y) | x > y
`%<=%` <- function(x, y) all.equal(x, y) | x < y
c(1-.9)>=.1
c(1-.9)%>=% .1

Resources