【问题标题】:Rcpp and int64 NA valueRcpp 和 int64 NA 值
【发布时间】:2020-04-23 11:35:01
【问题描述】:

如何在 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>

【问题讨论】:

  • 您不能在memcpy 之后使用NA_REAL,因为此时位模式是int64 之一。
  • 我还要编辑标题。 默认 64 位 NA 只是 NA_real,这不是您的问题所在。
  • 但是 memcpy 只复制 64 位 (sizeof(double)) 对吗?所以res[0]val 获得64 位,然后设置res[1] = ... 使用接下来的64 位。我同意结果,但不要真正遵循您的第一条评论。
  • 重点是向量的内容然后逐位成为int64_t,它只是“停放在”@ 987654333@ 向量(又名NumericVector)。没有神奇的逻辑副本。 Jems 正在亲手完成所有繁重的工作。包括映射 NA。
  • 那个。是。什么。我有。到过。试。到。解释。例如,查看现有 NA 定义的 R 源。查看一些使用int64 的包,看看它们做了什么。

标签: r rcpp na bit64


【解决方案1】:

好吧,我想我找到了答案……(不是很漂亮,但很有效)。

简答:

// [[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 年 4 月 23 日创建

我们看到它是10000...。这可以在Rcppint64_t val = 1ULL &lt;&lt; 63; 中重新创建。使用memcpy() 而不是使用= 进行简单分配可确保不会更改任何位!

【讨论】:

  • 是的。如果您查看一些源代码包,您会看到相应的 #define 语句将一位模式(通常是 minmax)声明为 NA 值。
【解决方案2】:

这真的要简单得多。我们在 R 中具有 int64 的行为,由(几个)附加包提供,其中最好的是 bit64 为我们提供了 integer64 S3 类和相关行为。

内部defines the NA如下:

#define NA_INTEGER64 LLONG_MIN

这就是全部。 R 及其包是最重要的 C 代码,LLONG_MIN 存在并(几乎)一直追溯到创始人。

这里有两节课。第一个是 IEEE 为 浮点值 定义 NaN 和 Inf 的扩展。 R 实际上远远超出并为它的每个类型添加了NA。几乎以上述方式:通过保留一个特定的位模式。 (在一种情况下,是两位原始 R 创作者之一的生日。)

另一个是欣赏 Jens 使用 bit64 包和所有所需的转换和运算符函数所做的大量工作。 无缝 转换所有可能的值,包括 NA、NaN、Inf、... 是一项不小的任务。

而且这是一个没有太多人知道​​的简洁主题。很高兴您提出这个问题,因为我们现在在这里有记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-28
    相关资源
    最近更新 更多