Search code examples
c++rfloating-pointrcpp

handling of floating points in rcpp: a value of -0 in R becomes 0 in C++ using Rcpp


A parameter with value of -0 in R becomes 0 in C++ world when using Rcpp. Here is a minimal example that demonstrates this.

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)

Here is the output:

[1] "sign in R -1"
v is zero

In short, The difference in -0 and 0 vanishes. Is this a bug? Is there any work around?


Solution

  • There is no bug. The behaviour is as expected: the int type in C++ (or virtually anywhere else) has no negative zero representation. The distinction between +0 and −0 only exists in IEEE floating point types. The number literal you have in R is a floating point number (to get an integral type, use the L suffix: 0L). But your C++ code intentionally converts it to int and therefore coerces it to 0, dropping the sign information.

    Furthermore, your C++ code does not actually check for the sign of the value: the same code in R would also output “v is zero” rather than “v is negative”:

    a = -0
    if (a < 0) "negative" else if (a == 0) "zero" else "positive"
    # [1] "zero"
    

    By contrast, we can verify that C++ does in fact preserve signed 0:

    Rcpp::cppFunction("
      void signCheck(NumericVector v) {
        Rcout << std::signbit(v[0]);
      }
    ")
    signCheck(-0)
    # 1
    

    (std::signbit returns true for negative numbers, which is indicated here by the output 1.)