Question

This is a really basic question, but I've never fully convinced myself that my intuitive answer of "it makes no difference" is correct, so maybe someone has a good way to understand this:

If all I want to do with one of the primitive numeric types in Java is bitwise arithmetic, can I simply treat it as if it was an unsigned value or do I need to avoid negative numbers, i.e. keep the highest order bit always set to 0? For example, can I use an int as if it was an unsigned 32-bit number, or should I only use the lowest 31 bits?

I'm looking for as general an answer as possible, but let me give an example: Let's say I want to store 32 flags. Can I store all of them in a single int, if I use something like

store = store & ~(1 << index) | (value << index)

to set flag index to value and something like

return (store & (1 << index)) != 0

to retrieve flag index? Or could I run into any sort of issues with this or similar code if I ever set the flag with index 31 to 1?

I know I need to always be using >>> instead of >> for right shifting, but is this the only concern? Or could there be other things going wrong related to the two's complement representation of negative numbers when I use the highest bit?

Was it helpful?

Solution

There are legitimate reasons to use >> as well in that context (a common case is when making a mask that should be 0 or -1 directly, without having to negate a mask that is 0 or 1), so there is really no concern at all. Just be careful of what you're doing to make sure it matches your intent.

Operations that care about signedness (ie they have distinct signed and unsigned forms with different semantics) are:

  • right shift
  • division (unsigned form not available in Java)
  • modulo (unsigned form not available in Java)
  • comparisons (except equality) (unsigned forms not available in Java)

Operations that don't care about signedness are:

  • and
  • or
  • xor
  • addition
  • subtraction
  • two's complement negation (-x means ~x + 1)
  • one's complement (~x means -x - 1)
  • left shift
  • multiplication

OTHER TIPS

I know I need to always be using >>> instead of >> for right shifting, but is this the only concern?

Yes, this is the only concern. Shifting left works the same on signed and unsigned numbers; same goes for ANDing, ORing, and XORing. As long as you use >>> for shifting right, you can use all 32 bits of a signed int.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top