gpt4 book ai didi

c - R 中位操作的 31 位限制

转载 作者:太空宇宙 更新时间:2023-11-03 23:49:10 25 4
gpt4 key购买 nike

我正在尝试绕过 R 中位操作的 31 位限制。我可以在纯 R 中执行此操作,但我的问题是关于在 C 中实现此操作以便在 R 中使用。

例子

比如我有数据

> x = c(2147028898, 2147515013)

其中每个元素最多 32 位,无符号,我想对其进行位操作,例如(但不限于)(x >> 20) & 0xFFF。最终目标是在单个函数中使用许多此类操作。

这两个数的位长不同。

> log2(x)
[1] 30.99969446331090239255 31.00002107107989246515

R 中的正常按位运算会产生以下结果,即为两者中较大的一个引入 NA。

> bitwShiftR(x,20)
[1] 2047 NA
Warning message:
In bitwShiftR(x, 20) : NAs introduced by coercion
> bitwAnd(x,20)
[1] 0 NA
Warning message:
In bitwAnd(x, 20) : NAs introduced by coercion

R 包“bitops”的解决方法

bitops package 做我想做的,但我的最终目标是更高级的东西,我希望能够使用 C,见下文。

> library(bitops)
> bitShiftR(x,20)
[1] 2047 2048

我看过这个包的C代码,但我不是很明白。一定要那么复杂,还是只是为了优化矢量化输入和输出?

C 中的解决方法(问题)

我的代码如下,到目前为止只是一个简单的表达式。我在 C 中尝试了不同的类型,但无济于事。

#include <R.h>

void myBitOp(int *x, int *result) {
*result = (*x >> 20) & 0xFFF;
}

然后我在 64 位机器上用 R CMD SHLIB myBitOp.c 编译。

$uname -a
Linux xxxxxxxxx 3.0.74-0.6.8-xen #1 SMP Wed May 15 07:26:33 UTC 2013 (5e244d7) x86_64 x86_64 x86_64 GNU/Linux

在 RI 中我加载它

> dyn.load("myBitOp.so")
> myBitOp <- function(x) .C("myBitOp", as.integer(x), as.integer(0))[[2]]

当我运行该函数时,我会返回

> myBitOp(x[1])
[1] 2047
> myBitOp(x[2])
Error in myBitOp(x[2]) : NAs in foreign function call (arg 1)
In addition: Warning message:
In myBitOp(x[2]) : NAs introduced by coercion

所以问题是,为什么我用这段 C 代码得到这些 NA,我该如何修复它?顺便说一下,返回值总是比 31 位小得多。

谢谢!

更新

在进一步研究 bitops 代码并浏览 this presentation 之后在其他链接中,我想出了这段代码(这里有额外的矢量化)

#include <R.h>
#include <Rdefines.h>

SEXP myBitOp(SEXP x) {
PROTECT (x = AS_NUMERIC(x) ) ;
double *xx = NUMERIC_POINTER(x);

SEXP result = PROTECT(NEW_NUMERIC(length(x)));
double *xresult = NUMERIC_POINTER(result);

for( int i=0; i < length(x); i++) {
xresult[i] = (double) ((((unsigned int) xx[i]) >> 20) & 0xFFF);
}
UNPROTECT(2);

return(result);
}

编译R CMD SHLIB myBitOp.c

在 R 中:

> dyn.load("myBitOp.so")
> myBitOp <- function(x) .Call("myBitOp", x)
> myBitOp(x)
[1] 2047 2048

我还不完全理解为什么或如何,但它有效,至少对于这个例子似乎有效。

最佳答案

as.integer(x) 的第二个元素将为 NA,因为它大于 .Machine$integer.maxNAOK = FALSE 在您对 .C 的调用中,因此您输入的 NA 会导致错误。如果您设置 NAOK = TRUE,您对 .C 的调用将“成功”(因为在这种情况下,NA 在技术上是 NA_integer_ ,这是C中的一个特殊的int值)。

您必须发挥创意才能解决这个问题。您可以尝试将 > 2^31-1 的值拆分为两个值,将它们都传递给 C,将它们转换为无符号整数,对它们求和,将结果转换为有符号整数,然后传回 R。

关于c - R 中位操作的 31 位限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25284712/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com