在R中实现nextafter功能
在R中是否有任何功能的实现,以便可以从给定的浮点数中获得下一个可表示的浮点数。这类似于C标准库中的函数。像在R中实现nextafter功能,r,floating-point,R,Floating Point,在R中是否有任何功能的实现,以便可以从给定的浮点数中获得下一个可表示的浮点数。这类似于C标准库中的函数。像number+.Machine$double.eps这样的方案一般不起作用。不起作用,但有两种方法可以实现: 使用C 如果您想要获得nextafter()函数的确切功能,可以编写一个C函数作为函数的接口,以满足以下两个约束: 该函数不返回值。所有的工作都是作为“副作用”(改变参数的值)完成的 所有参数都是指针。偶数标量是R中的向量(长度为1) 然后,应将该函数编译为共享库: R CMD
number+.Machine$double.eps这样的方案一般不起作用。不起作用,但有两种方法可以实现:
使用C
如果您想要获得nextafter()
函数的确切功能,可以编写一个C函数作为函数的接口,以满足以下两个约束:
- 该函数不返回值。所有的工作都是作为“副作用”(改变参数的值)完成的
- 所有参数都是指针。偶数标量是R中的向量(长度为1)
然后,应将该函数编译为共享库:
R CMD SHLIB foo.c
对于类似UNIX的OSs。可以使用dyn.load(“foo.so”)
调用共享库。然后可以使用.C()
函数从R内部调用该函数
.C("foo", ...)
从R调用C的更深入的处理是
使用R
代码>号码+机器$2。EPS 是方法,但你必须考虑边缘情况,比如<代码> X-Y>机器$Unter。EPS 或如果<代码> 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)
}
}
如果您更喜欢Rcpp:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double nextAfter(double x, double y) {
return nextafter(x, y);
}
在之后是否需要(delta<.Machine$double.eps)
,否则如果?在第二种情况下,您是否应该使用.Machine$double.neg.eps
?谢谢您的回答,我希望需要本机呼叫。不幸的是,对于R,这不起作用,100+.Machine$double.eps==100
是TRUE
@RónánDaly:您可以在R中完成所有操作,但必须为.Machine$double.eps添加一个因子。它只保证1的下一个可表示数字。对于其他数字,您必须使其更大。我已经添加了一些代码来修复这个问题,所以对于整数它应该在-100和100之间工作。不过,还需要更多的测试。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double nextAfter(double x, double y) {
return nextafter(x, y);
}
sprintf("%.20f", 1)
#[1] "1.00000000000000000000"
sprintf("%.20f", nextAfter(1, 2))
#[1] "1.00000000000000022204"