2

The following code produces surprising results:

x<-round(c(.1,-.1))
x==0 #TRUE TRUE
x<0 #FALSE FALSE
formatC(x) #"0", "-0"

x passes every test I know how to do to be zero, but somehow formatC knows that it was once a negative number. Where is the carryover coming from?

jntrcs
  • 527
  • 1
  • 5
  • 13
  • Interesting. Why not make this an answer? Any function to check that signed bit that you know of in R? – jntrcs Aug 03 '18 at 15:49

1 Answers1

3

Floating point numbers have a bit dedicated to the sign of a number. The round() function doesn't flip that flag in the case of rounding to 0. You can have a signed zero value when working with floating point numbers.

You can see the hex value representation of the bytes of a number with sprintf. For example

x <- c(.1,-.1)
sprintf("%a", x)
# [1] "0x1.999999999999ap-4"  "-0x1.999999999999ap-4"
sprintf("%a", round(x))
# [1] "0x0p+0"  "-0x0p+0"

In this representation the signed bit is indicated with the presences or absence of the "-" in the string. We can see that the rounded version keeps the sign bit the same.

For all intents and purposes, the -0 will act just like a regular 0. You can get rid of the negative by adding 0 to your result.

formatC(round(x)+0)
# [1] "0" "0"

But really this is just happening because you are using the low-level formatC function. Even R itself doesn't distinguish between 0 and -0 when displaying the numbers. Because R tries to hide this detail, I don't think you can distinguish between the two in R. you'd have to write your own C/C++ code to check the sign digit yourself.

For more non-R specific discussion see: Negative Zero in C

MrFlick
  • 195,160
  • 17
  • 277
  • 295