[英]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.