2014-02-26 65 views
4

R中是否有任何功能實現,以便可以從給定的浮點數中獲取下一個可表示的浮點數。這將與C標準庫中的nextafter函數類似。一般而言,諸如number + .Machine$double.eps之類的方案不起作用。在R中實現nextafter功能

回答

4

沒有,但有兩種方法,你可以把它:

用C

如果你想nextafter()功能的確切功能,你可以寫一個C函數,它作爲一個接口以滿足以下兩個約束條件:

  • 函數不返回值。所有的工作都是作爲「副作用」來完成的(改變參數的值)。
  • 所有參數都是指針。甚至標量是在R.

(的長度的一個)載體然後,該功能應該被編譯爲一個共享庫:

R CMD SHLIB foo.c 

爲類UNIX操作系統。共享庫可以使用dyn.load("foo.so")來調用。然後,可以從在'r使用來自R調用C的.C()功能

.C("foo", ...) 

更深入治療是here調用該函數。

基於R

number + .Machine$double.eps是要走的路,但你必須要考慮極端情況,例如,如果x - y < .Machine$double.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) 
    } 
} 

現在,不同於C,如果你想查詢的整數,你可以在同一個函數這樣做,但你需要改變基於該類型的增量。如預期超過2。有需要由.Machine$double.eps相乘,使其大到足以導致數字是不同的因素較大的數字

UPDATE 上面的代碼沒有執行。它與2加1的最近功率有關。如果你喜歡RCPP

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 
} 
+1

做你想做一個'(DELTA <.Machine $ double.eps)'在你的'else if'之後? –

+0

在第二種情況下,你應該使用'.Machine $ double.neg.eps'嗎? –

+0

是的,謝謝。兩者都已修復。 –

3

:您可以瞭解其工作原理與下面的代碼的想法

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
double nextAfter(double x, double y) { 
    return nextafter(x, y); 
} 
R中

然後:

sprintf("%.20f", 1) 
#[1] "1.00000000000000000000" 
sprintf("%.20f", nextAfter(1, 2)) 
#[1] "1.00000000000000022204"