rcpp 中浮点的处理:R 中的 -0 值在使用 Rcpp 的 C++ 中变为 0

opt*_*guy 0 c++ floating-point r rcpp

当使用 Rcpp 时,R 中值为 -0 的参数在 C++ 世界中变为 0。这是一个演示这一点的最小示例。

library("Rcpp")
cppFunction(' 
 void signCheck(NumericVector v ) {
   int vint = Rcpp::as<int>(v);
   if (vint < 0) {
      Rcout << "    v is negative";
   }
   else if (vint == 0) {
      Rcout << "v is zero";
   }
   else {
      Rcout << "v is positive";
   }

 }
')



a = -0
print(paste("sign in R", sign(1/a)))
signCheck(a)
Run Code Online (Sandbox Code Playgroud)

这是输出:

[1] "sign in R -1"
v is zero
Run Code Online (Sandbox Code Playgroud)

简而言之,-0 和 0 之间的差异消失了。这是一个错误吗?有什么解决办法吗?

Kon*_*lph 8

没有错误。行为符合预期:intC++ 中的类型(或几乎其他任何地方)没有负零表示。+0 和 \xe2\x88\x920 之间的区别仅存在于 IEEE 浮点类型中。R 中的数字文字是浮点数(要获得整型,请使用后缀L0L)。但是您的 C++ 代码故意将其转换为 0 int,从而将其强制为 0,从而删除符号信息。

\n

此外,您的 C++ 代码实际上并不检查值的符号:R 中的相同代码也会输出 \xe2\x80\x9cv is Zero\xe2\x80\x9d 而不是 \xe2\x80\x9cv is negative\xe2 \x80\x9d:

\n
a = -0\nif (a < 0) "negative" else if (a == 0) "zero" else "positive"\n# [1] "zero"\n
Run Code Online (Sandbox Code Playgroud)\n

相比之下,我们可以验证 C++实际上保留了有符号 0

\n
Rcpp::cppFunction("\n  void signCheck(NumericVector v) {\n    Rcout << std::signbit(v[0]);\n  }\n")\nsignCheck(-0)\n# 1\n
Run Code Online (Sandbox Code Playgroud)\n

std::signbit返回true负数,此处由输出指示1。)

\n

  • @EricPostpischil 是吗?我没有写“或*任何地方*其他”,这会是不同的(并且可能是错误的)。“准确地”使用定义不太明确的“其他地方”是一个有意识的选择,这样我就可以避免包含一个曲折的免责声明,从而分散对要点的注意力。好吧,现在这个曲折的免责声明已经在评论中了。 (2认同)