在R中实现nextafter功能

在R中实现nextafter功能,r,floating-point,R,Floating Point,在R中是否有任何功能的实现,以便可以从给定的浮点数中获得下一个可表示的浮点数。这类似于C标准库中的函数。像number+.Machine$double.eps这样的方案一般不起作用。不起作用,但有两种方法可以实现: 使用C 如果您想要获得nextafter()函数的确切功能,可以编写一个C函数作为函数的接口,以满足以下两个约束: 该函数不返回值。所有的工作都是作为“副作用”(改变参数的值)完成的 所有参数都是指针。偶数标量是R中的向量(长度为1) 然后,应将该函数编译为共享库: R CMD

在R中是否有任何功能的实现,以便可以从给定的浮点数中获得下一个可表示的浮点数。这类似于C标准库中的函数。像
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"