[Rd] zapsmall(x) for scalar x

Gregory Warnes greg @end|ng |rom w@rne@@net
Sat Dec 16 23:34:18 CET 2023


I was quite suprised to discover that applying `zapsmall` to a scalar value has no apparent effect.  For example: 

> y <- 2.220446e-16
> zapsmall(y,)
[1] 2.2204e-16

I was expecting zapsmall(x)` to act like

> round(y, digits=getOption('digits'))
[1] 0

Looking at the current source code, indicates that `zapsmall` is expecting a vector:

zapsmall <-
function (x, digits = getOption("digits")) 
{
    if (length(digits) == 0L) 
        stop("invalid 'digits'")
    if (all(ina <- is.na(x))) 
        return(x)
    mx <- max(abs(x[!ina]))
    round(x, digits = if (mx > 0) max(0L, digits - as.numeric(log10(mx))) else digits)
}

If `x` is a non-zero scalar, zapsmall will never perform rounding.

The man page simply states:
zapsmall determines a digits argument dr for calling round(x, digits = dr) such that values close to zero (compared with the maximal absolute value) are ‘zapped’, i.e., replaced by 0.

and doesn’t provide any details about how ‘close to zero’ is defined. 

Perhaps handling the special when `x` is a scalar (or only contains a single non-NA value)  would make sense:

zapsmall <-
function (x, digits = getOption("digits")) 
{
    if (length(digits) == 0L) 
        stop("invalid 'digits'")
    if (all(ina <- is.na(x))) 
        return(x)
    mx <- max(abs(x[!ina]))
    round(x, digits = if (mx > 0 && (length(x)-sum(ina))>1 ) max(0L, digits - as.numeric(log10(mx))) else digits)
}

Yielding:

> y <- 2.220446e-16
> zapsmall(y)
[1] 0

Another edge case would be when all of the non-na values are the same:

> y <- 2.220446e-16
> zapsmall(c(y,y))
[1] 2.220446e-16 2.220446e-16

Thoughts?


Gregory R. Warnes, Ph.D.
greg using warnes.net
Eternity is a long time, take a friend!



	[[alternative HTML version deleted]]



More information about the R-devel mailing list