[Rd] Floating-point-related surprising behaviour in boot:::norm.inter

Andreï V. Kostyrka @ndre|@ko@tyrk@ @end|ng |rom gm@||@com
Tue Mar 21 01:59:38 CET 2023


Dear all,

I have been implementing some bootstrap-related methods, and came across
this theoretically undesirable behaviour in the computation of bootstrap
quantiles. The manual says:

‘Interpolation on the normal quantile scale is used when a non-integer
order statistic is required.’

Theoretically, when R=999 and (R+1)*alpha is integer, then, the
calculations of the 95% CI should never contain non-integer order
statistics, right?

No – due to the fractional nature of the probabilities. Consider R=999 and
conf=0.95; then, the second argument to boot:::norm.inter is

alpha <- (1 + c(conf, -conf))/2
print(alpha, 20) # c(0.974999999999999977796, 0.025000000000000022204)
# print(0.025, 20) yields 0.025000000000000001388

Looks like both numbers times (B+1) should not be integers, right?.. Oddly
enough, one of them is integer, and one of them isn’t:

R <- 999
rk <- (R + 1) * alpha
k <- trunc(rk)
ints <- (k == rk) # TRUE FALSE

k - rk # 0.000000e+00 -2.131628e-14

This is why the subsequent variable `temp` (containing the indices of
non-integer order statistics) becomes equal to 2.

Yes, the amount of correction due to interpolation is minuscule (around
1e-16), but this code should not have been invoked in the first place. This
kind of unintended behaviour can be prevented through a more relaxed check:

ints <- abs(k - rk) < R * .Machine$double.eps

The FP-related error is proportional to R, e.g. if R=99999, then, abs(k -
rk) = 0.000000e+00 2.273737e-12). Therefore, I believe that fuzzy
comparison (with tolerance proportional to R) should replace the faulty
strict-equality-based one. Then, a check can be carried out based on `if
(any(!ints))` to invoke the interpolation only if the order statistics are
really non-integer.

Yours sincerely,
Andreï V. Kostyrka

	[[alternative HTML version deleted]]



More information about the R-devel mailing list