Consider the following R function
is.sqrt <- function(x, y){
if(x^2 == y) TRUE
else FALSE
}
which answers whether x is the square ro
you can use all.equal
in your function, which "tests if two objects are 'nearly' equal"
is.sqrt <- function(x, y){
isTRUE(all.equal(x^2,y)
}
is.sqrt(sqrt(2), 2)
# TRUE
is.sqrt(sqrt(2), 3)
# FALSE
You can use the near
function from dplyr
, it has a built-in tolerance.
is.sqrt <- function(x, y) {
near(x^2, y)
}
is.sqrt(sqrt(2), 2)
> TRUE
Another option could be to use all.equal.numeric
itself.
Option-A)
is.sqrt <- function(x, y){
isTRUE(all.equal.numeric(x^2, y))
}
#> is.sqrt(sqrt(2),2)
#[1] TRUE
Option-B)
Using tolerance limit double precision. Optionally one can use .Machine.double.eps
but I had preferred to use a fixed value as 1e-8
.
is.sqrt_abs_tol<- function(x, y){
tol <- 1e-8 # OR .Machine$double.eps can be used
abs(x^2 - y) <= tol
}
#> is.sqrt_abs_tol(sqrt(2), 2)
#[1] TRUE
As agreed with @docendodiscimus, I thought do some performance analysis about these options.
library(microbenchmark)
library(dplyr)
is.sqrt_Dan <- function(x, y){
isTRUE(all.equal(x^2,y))
}
is.sqrt_MKR <- function(x, y){
isTRUE(all.equal.numeric(x^2, y))
}
is.sqrt_Leon <- function(x, y) {
near(x^2, y)
}
is.sqrt_abs_tol<- function(x, y){
tol <- 1e-5
abs(x^2 - y) <= tol
}
microbenchmark(
is.sqrt_Leon(sqrt(2), 2),
is.sqrt_Dan(sqrt(2), 2),
is.sqrt_MKR(sqrt(2), 2),
is.sqrt_abs_tol(sqrt(2), 2),
times=1000L
)
expr min lq mean median uq max neval
is.sqrt_Leon(sqrt(2), 2) 2369 3948 4736.816 4737 5132 60001 1000
is.sqrt_Dan(sqrt(2), 2) 36711 38291 44590.051 39474 41844 2750542 1000
is.sqrt_MKR(sqrt(2), 2) 32369 33949 38130.556 35133 37501 211975 1000
is.sqrt_abs_tol(sqrt(2), 2) 395 1185 4571.833 1579 1580 3107387 1000
Few observations from the analysis above:
near
function from dplyr
is faster than all.equal
variants.all.equal.numeric
is slightly faster than all.equal
abs
and tolerance
is super-fast.