1

I was reading this page on the "Code Ranch" which talks about variables.

It was discussing "signed primitives," and was saying that 0 is counted as a negative???

I always thought 0 was positive in these cases?

All of these integer types are SIGNED. The leftmost bit represents the sign (positive or negative) and is NOT part of the value. So with a byte, for instance, you don't get the whole 8 bits to represent your value. You get 7. This gives you a range, for bytes, of : (-2 to the 7th) through (2 to the 7th) -1. Why that little -1 on the end? Because zero is in there, and zero counts as negative. Works the same way with the others.

http://www.javaranch.com/campfire/StoryCups.jsp

But when looking at this post Why is the range of bytes -128 to 127 in Java?

One comment mentions "0 is positive by default." It also talks about "Two's Compliment," and mentions anything with a '1' in the left-most bit would be "negative," which 0 doesn't have that....

Also, if 0 was negative -128 to 0 is 129 negatives, with 127 positives, which doesn't make sense....

So I'm curious if this is an error, or if 0 is negative, and why?

Also, I was reading this thread How can a primitive float value be -0.0? What does that mean?

That was talking about a float with value of -0.0, and adding a '0.0' to it in order to make it a "neutral/positive" 0.0....

So I'm curious if both positive and negative zeroes exist in floats, or does it exist in both floating point and integer primitives?????

Also, when I was Googling answers for this, mention of "Zero being neither positive-negative/ being both positive-negative...." Curious if/when this applies in our languages?

Thanks

Community
  • 1
  • 1
XaolingBao
  • 984
  • 14
  • 33
  • 2
    What does it mean to "count as a negative"? Why does it matter? (from a programming perspective) – Oliver Charlesworth Oct 15 '15 at 22:07
  • Zero is not negative, and I agree that it doesn't matter either way. – androiddev19 Oct 16 '15 at 03:18
  • It might not matter for most people, in regards to programming applications, but it might at some point...? Either way, the fact they were passing off this information as true, doesn't look good for the rest of their information, granted it's a legit site that's been around for a long time. – XaolingBao Oct 16 '15 at 04:59

1 Answers1

4

This is a complex question with a number of facets to it so I’m going to try to break it down as best I can.

First, there’s the mathematical concept of zero and whether it’s positive or negative. Unfortunately, the answer to that, essentially, is that it’s context dependent and sometimes it's reasonable to include zero in a set of positive numbers or negative numbers. Mathematicians recognise the ambiguity and have a special term for when they need to be clear about whether zero is in a particular set of numbers or not - “non-negative” and “non-positive” both include zero. Some ‘common-sense’ definitions of positive and negative allows for an exclusive comparison with zero, which puts zero in the special case of being neither positive or negative. Others have an inclusive notion of positive or negative, which can make zero both positive and negative. https://math.stackexchange.com/questions/26705/is-zero-positive-or-negative

So what does that mean for the Java language? Again, there are a number of different cases to consider - primitive integral types, primitive floating-point types, boxed primitives, the arbitrary precision classes BigDecimal and BigInteger, and, most importantly, what effects are visible?

Java represents primitive integral types using the 2s complement system and so it only has a single representation for zero. In the sense that 0 does not have the sign bit set it might be reasonable to say that 0 is positive. However, it's really a moot point since there isn't really anything else in the language which is concerned with whether zero is positive or negative and so it really doesn't have a practical effect. The boxed versions of these types have very much the same behaviour.

What 2’s complement does mean though, is that any given range of numbers is unevenly balanced around zero. So, if you take an 8-bit value you can represent 256 values with it. One of those is 0, which leaves you with 255 non-zero values. However you split the remainder you get one side slightly larger than the other. 2’s complement makes -128 a valid negative value and 127 the largest positive value which you can represent with 8 bits. The same is true for the larger integral types int and long - they can represent one more non-zero negative integer than non-zero positive integer. This is neither a bug nor an error, it's a simple fact.

For the floating point primitive types, double and float, Java uses IEEE 754 to represent them. This allows for two different ways of representing 0.0 and so, technically, every zero is either -0.0 or +0.0. The IEEE standard, however, is clear that those two values are practically indistinguishable - they’re equal and so -0.0 == +0.0 evaluates to true. For most mathematical operations, -0.0 and +0.0 have the same effect. That is until you attempt something which generates Inf. So, dividing by -0.0 will get you -Inf and dividing by +0.0 will get +inf. Either way your calculation has entered a black hole. Luckily, all NaNs are the same so -0.0 / 0.0 will get you Nan in exactly the same way as 0.0 / 0.0. For other mathematical operations, -0.0 acts consistently. So, Math.sqrt(-0.0) is -0.0 and Math.sqrt(0.0) is 0.0. Math.abs(-0.0) will return 0.0. But there's really very little difference between -0.0 and 0.0.

What can matter is that when you display the numbers in a formatted String the sign remains. If you really care about it then you can use Math.abs() to turn a 'negative' zero into a 'positive' zero, but it's usually not a problem worth thinking about.

There’s a curious effect when it comes the boxed types for floating point numbers and that related to the 'equals()’ method. Primitive types have -0.0 == +0.0 evaluating to true. However Double.valueOf(-0.0).equals(Double.valueOf(+0.0)) evaluates to false, which is documented but counter-intuitive and so potentially confusing. When combined with auto-boxing and auto-unboxing this can have some confusing side effects - e.g. Double.valueOf(-0.0) == Double.valueOf(+0.0) is false but -0.0 == +0.0 is true. Meanwhile, Double.valueOf(-0.0) == +0.0d is true. As ever with Java - be a little bit wary of boxed primitives and always be careful about mixing boxed and unboxed primitives.

BigDecimal throws a further spanner in the works by having a slightly different implementation of equals(). So, BigDecimal.valueOf(-0.0).equals(BigDecimal.valueOf(0.0)) evaluates to true, but BigDecimal.valueOf(-0.0).equals(BigDecimal.ZERO) is false. This is because the scale is considered along with the value. BigDecimal.ZERO is actually 0, which is seen as a different value from 0.0, which is again different from 0.00 - new BigDecimal("-0.0").equals(new BigDecimal("-0.00")) evaluates to false.

Another thing we can look at is the Math.signum() function, which is defined as returning -1, 0 or 1 depending on whether the argument is negative, zero or positive. The same is true for the signum method on the BigInteger and BigDecimal classes in the java.math package. Unfortunately the Math.signum() function returns a double, and so you get -0.0 for -0.0 and 0.0 for 0.0, whereas BigDecimal.signum() returns an int. But what signum does imply is that however you define zero, it’s not really positive or negative.

sisyphus
  • 5,566
  • 1
  • 20
  • 32
  • I just want to say thanks so much for replying to me, and sorry it took so long for me to reply back, I forgot that I had a reply here. I upvoted, and put this as the answer, but will make that final choice after reading it... IT seems like a ton of info though, so I'm sure this will be what I want :). – XaolingBao Dec 23 '15 at 19:30