簡體   English   中英

Rcpp 和 int64 NA 值

[英]Rcpp and int64 NA value

如何在 64 位向量中將 NA 值從 Rcpp 傳遞到 R?

我的第一個方法是:

// [[Rcpp::export]]                                     
Rcpp::NumericVector foo() {
  Rcpp::NumericVector res(2);

  int64_t val = 1234567890123456789;
  std::memcpy(&(res[0]), &(val), sizeof(double));
  res[1] = NA_REAL;

  res.attr("class") = "integer64";
  return res;
}

但它產生

#> foo()
integer64
[1] 1234567890123456789 9218868437227407266

我需要得到

#> foo()
integer64
[1] 1234567890123456789 <NA>

這真的非常非常簡單。 我們在 R 中有一個int64的行為,由(幾個)附加包提供,其中最好的是bit64給我們integer64 S3 class 和相關行為。

在內部定義 NA如下:

#define NA_INTEGER64 LLONG_MIN

這就是全部。 R 及其包最重要的是 C 代碼, LLONG_MIN存在於那里並且(幾乎)一直追溯到開國元勛。

這里有兩個教訓。 第一個是 IEEE 為浮點值定義 NaN 和 Inf 的擴展。 R 實際上遠遠超出了它的每個類型並添加了NA 與上面的方法差不多:通過保留一個特定的位模式。 (其中一個是 R 最初的兩位創作者之一的生日。)

另一個是欣賞 Jens 使用bit64 package 以及所有必需的轉換和運算符函數所做的大量工作。 無縫轉換所有可能的值,包括 NA、NaN、Inf ……不是一項小任務。

這是一個鮮為人知的話題。 我很高興你問了這個問題,因為我們現在在這里有一個記錄。

好吧,我想我找到了答案......(不漂亮,但工作)。

簡短回答:

// [[Rcpp::export]]                                     
Rcpp::NumericVector foo() {
  Rcpp::NumericVector res(2);

  int64_t val = 1234567890123456789;
  std::memcpy(&(res[0]), &(val), sizeof(double));

  # This is the magic:
  int64_t v = 1ULL << 63;
  std::memcpy(&(res[1]), &(v), sizeof(double));

  res.attr("class") = "integer64";
  return res;
}

這導致

#> foo()
integer64
[1] 1234567890123456789 <NA>

更長的答案

檢查bit64如何存儲NA

# the last value is the max value of a 64 bit number
a <- bit64::as.integer64(c(1, 2, NA, 9223372036854775807))
a
#> integer64
#> [1] 1    2    <NA> <NA>
bit64::as.bitstring(a[3])
#> [1] "1000000000000000000000000000000000000000000000000000000000000000"
bit64::as.bitstring(a[4])
#> [1] "1000000000000000000000000000000000000000000000000000000000000000"

reprex package (v0.3.0) 創建於 2020-04-23

我們看到它是一個10000... 這可以在Rcpp中用int64_t val = 1ULL << 63; . 使用memcpy()而不是使用=進行簡單賦值可確保不會更改任何位!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM