R 中是否有任何功能实现,以便可以从给定的浮点数中获取下一个可表示的浮点数。这将类似于C 标准库中的nextafter函数。诸如此类的方案number + .Machine$double.eps一般不起作用。
不,但有两种方法可以做到:
使用 C
如果您想要函数的确切功能nextafter(),您可以编写一个 C 函数作为函数的接口,以满足以下两个约束:
然后应该将该函数编译为共享库:
R CMD SHLIB foo.c
Run Code Online (Sandbox Code Playgroud)
适用于类 UNIX 操作系统。可以使用 调用共享库dyn.load("foo.so")。然后,您可以使用该.C()函数从 R 内部调用该函数
.C("foo", ...)
Run Code Online (Sandbox Code Playgroud)
从 R 调用 C 的更深入的处理是here。
使用 R
number + .Machine$double.eps是要走的路,但您必须考虑边缘情况,例如 ifx - y < .Machine$double.eps或 if x == y。我会这样写函数:
nextafter <- function(x, y){
# Appropriate type checking and bounds checking goes here
delta = y - x
if(x > 0){
factor = 2^floor(log2(x)) + ifelse(x >= 4, 1, 0)
} else if (x < 0) {
factor = 65
}
if (delta > .Machine$double.eps){
return(x + factor * .Machine$double.eps)
} else if (delta < .Machine$double.eps){
return(x - factor * .Machine$double.eps)
} else {
return(x)
}
}
Run Code Online (Sandbox Code Playgroud)
现在,与 C 不同的是,如果您想检查整数,您可以在同一个函数中执行此操作,但您需要根据类型更改增量。
更新
对于大于 2 的数字,前面的代码没有按预期执行。有一个因素需要乘以.Machine$double.eps以使其足够大以导致数字不同。它与最近的 2 加 1 的幂有关。您可以通过以下代码了解这是如何工作的:
n <- -100
factor <- vector('numeric', 100)
for(i in 1:n){
j = 0
while(TRUE){
j = j + 1
if(i - j * .Machine$double.eps != i) break()
}
factor[i] = j
}
Run Code Online (Sandbox Code Playgroud)