Bitwise shift operation choice - java

Hello everyone I'm learning programming in java and I wanted to know why is the choice for
Sign bit propagation is ">>" and not ">>>"?
I would assume << and >> should have the same implementation.
Sorry if it sounds like a silly question :)
Thanks in advance!

The reason it works this way is because C and C++ used << for left shift and >> for right shift long before Java. Those languages have both signed and unsigned types, and for signed types the sign bit was propagated in the right-shift case.
Java does not have unsigned types, so they kept the behavior of C and C++ so as not to sow confusion and incur the undying wrath of developers the world over. Then they included >>> to provide a right-shift that treated the bit value as unsigned.

This question is really about reading James Gosling's mind :-). But my guess is that << and >> both make sense mathematically: << causes a number to be multiplied by 2 (barring overflow), and >> causes a number to be divided by 2--when you have sign propagation, this works whether the number is positive or negative. Perhaps the language designers thought this would be a more common use of the right shift than the operator that propagates 0's, which is more useful when integers are treated as strings of bits rather than actual numbers. Neither way is "right" or "wrong", and it's possible that if Gosling had had something different for breakfast that morning, he might have seen things your way instead...

Lets start with the questions that you didn't ask :-)
Q: Why is there no <<<?
A1: Because << performs the appropriate reverse operation for both >> and >>>.
>> N is equivalent to divide by 2N for a signed integer
>>> N is equivalent to divide by 2N for an unsigned integer
<< N is equivalent to multiply by 2N for both signed and unsigned integers
A2: Because the sign bit is on the left hand end, so "extending" it when you shift leftwards is nonsensical. (Rotating would make sense, but Java doesn't have any "rotate" operators. Reasons: C precedent, lack of hardware support in some instruction sets, rotation is rarely needed in Java code.)
Q: Why does only one of >> and >>> to sign extension
A: Because if they both did (or neither did) then you wouldn't need two operators.
Now for your questions (I think):
Q: Why did they choose >> to do sign extension and not >>>?
A: This is really unanswerable. As far as we know, there is no extant publicly available contemporaneous record of the original Oak / Java language design decisions. At best, we have to rely on the memory of James Gosling ... and his willingness to answer questions. AFAIK, the question has not been asked.
But my conjecture is that since Java integer types are (mostly) signed, it was thought that the >> operator would be used more often. In hindsight, I think Gosling et al got that right.
But this was NOT about copying C or C++. In those languages, there is only one right-shift operator (>>) and its behavior for signed integers is implementation defined!!. The >>> operator in Java was designed to fix that problem; i.e. remove the portability problem of C / C++ >>.
(Reference: Section 6.5.7 of the draft C11 Language spec.)
Next your comment:
I would assume << and >> should have the same implementation. By same implementation I mean same process but opposite direction.
That is answered above. From the perspective of useful functionality, >> and << do perform the same process for signed numbers but in different direction; i.e. division versus multiplication. And for unsigned numbers <<< corresponds to >> in the same way?
Why the difference? It is basically down to the mathematics of 2's complement and unsigned binary representations.
Note that you cannot perform the mathematical inverse of >> or >>>. Intuitively, these operators throw away the bits on the right end. Once thrown away, those bits cannot be recovered.
Q: So why don't they make << (or a hypothetical <<<) "extend" the right hand bit?
A: Because:
It is not useful. (I cannot think of any mainstream use-cases for extending the right hand bits of a number.)
There is typically no hardware support (... because it is not useful!)

Related

x86 80-bit floating point type in Java

I want to emulate the x86 extended precision type and perform arithmetic operations and casts to other types in Java.
I could try to implement it using BigDecimal, but covering all the special cases around NaNs, infinity, and casts would probably a tedious task. I am aware of some libraries that provide other floating types with a higher precision than double, but I want to have the same precision as the x86 80-bit float.
Is there a Java library that provides such a floating point type? If not, can you provide other hints that would allow to implement such a data type with less effort than coming up with a custom BigDecimal solution?
If you know that your Java code will actually run on an x86 processor, implement the 80-bit arithmetic in assembly (or C, if the C compiler supports that) and invoke with JNI.
If you are targeting a particular non-x86 platform, look at qemu code. There should be some way to rip out just the part that does 80-bit float operations. (Edit: qemu's implementation is SoftFloat.). Call it with JNI.
If you truly want cross-platform pure-Java 80-bit arithmetic, you could probably still compare it against the C implementation in open-source CPU emulators to make sure you're addressing the right corner cases.
An 80-bit value should be best held as combination of a long (for the mantissa) and an int for the exponent and sign. For many operations, it will probably be most practical to place the upper and lower halves of the long into separate "long" values, so the code for addition of two numbers with matching signs and exponents would probably be something like:
long resultLo = (num1.mant & 0xFFFFFFFFL)+(num2.mant & 0xFFFFFFFFL);
long resultHi = (num1.mant >>> 32)+(num2.mant >>> 32)+(resultLo >>> 32);
result.exp = num1.exp; // Should match num2.exp
if (resultHi > 0xFFFFFFFFL) {
exponent++;
resultHi = (resultHi + ((resultHi & 2)>>>1)) >>> 1; // Round the result
}
rest.mant = (resultHi << 32) + resultLo;
A bit of a nuisance all around, but not completely unworkable. The key is
to break numbers into pieces small enough that you can do all your math as
type "long".
BTW, note that if one of the numbers did not originally have the same exponent,
it will be necessary to keep track of whether any bits "fell off the end" when
shifting it left or right to match the exponent of the first number, so as to
be able to properly round the result afterward.
This is a bit the reverse of the java strictfp option, that restricts the calculations to 8 bytes where it does 80 bits.
So my answer is run a JVM on a 64 bit machine, maybe in some hypervisor/OS VM, so you have a develop platform.

Simple bitwise operation in Java

I'm writing code in Java using short typed variables. Short variables are normally 16 bits but unfortunately Java doesn't have unsigned primitive types so I'm using the 15 lower bits instead ignoring the sign bit. Please don't suggest changes to this part as I'm already quite far in this implementation... Here is my question:
I have a variable which I need to XOR.
In C++ I would just write
myunsignedshort = myunsignedshort ^ 0x2000;
0x2000 (hex) = 0010000000000000 (binary)
However, in Java, I have to deal with the sign bit also so I'm trying to change my mask so that it doesn't affect the xor...
mysignedshort = mysignedshort ^ 0xA000;
0xA000 (hex) = 1010000000000000 (binary)
This isn't having the desired effect and I'm not sure why. Anyone can see where I'm going wrong?
Regards.
EDIT: ok you guys are right, that bit wasn't causing the issue.
the issue comes when I'm shifting bits to the left.
I accidentally shift bits into the sign bit.
mysignedshort = mysignedshort << 1;
Any any ideas how to avoid this new prob so that if it shifts into the MSB then nothing happens at all? or should I just do a manual test? Theres a lot of this shifting in the code though so I would prefer a more terse solution.
Regards.
Those operations don't care about signedness, as mentioned in the comments. But I can expand on that.
Operations for which the signed and unsigned versions are the same:
addition/subtraction
and/or/xor
multiplication
left shift
equality testing
Operations for which they are different:
division/remainder
right shift, there's >> and >>>
ordered comparison, you can make a < b as (a ^ 0x80000000) < (b ^ 0x80000000) to change from signed to unsigned, or unsigned to signed.
You can also use (a & 0xffffffffL) < (b & 0xffffffffL) to get an unsigned comparison, but that doesn't generalize to longs.

Java/Python MD5 implementation- how to overcome unsigned 32-bit requirement?

I'm attempting to implement MD5 (for curiosity's sake) in Python/Java, and am effectively translating the wikipedia MD5 page's pseudocode into either language. First, I used Java, only to encounter frustration with its negative/positive integer overflow (because unsigned ints aren't an option, for-all integer,-2147483648 <= integer <= 2147483647). I then employed Python, after deciding that it's better suited for heavy numerical computation, but realized that I wouldn't be able to overcome the unsigned 32-bit integer requirement, either (as Python immediately casts wrapped ints to longs).
Is there any way to hack around Java/Python's lack of unsigned 32-bit integers, which are required by the aforementioned MD5 pseudocode?
Since all the operations are bitwise operations, they wouldn't suffer from sign extension (which would cause you problems), except for right shift.
Java has a >>> operator for this purpose.
As a note beforehand - I don't know if this is a good solution, but it appears to give the behaviour you want.
Using the ctypes module, you can access the underlying low-level data-type directly, and hence have an unsigned int in Python.
Specifically, ctypes.c_uint:
>>> i = ctypes.c_uint(0)
>>> i.value -= 1
>>> i
c_uint(4294967295)
>>> i.value += 1
>>> i
c_uint(0)
This is arguably abuse of the module - it's designed for using C code easily from within Python, but as I say, it appears to work. The only real downside I can think of is that I assume ctypes is CPython specific.

Advantage of >> operator over / operator

What is the advantage of using >> operator over / operator? It was extensively used in the code I am maintaining.
For eg,
int width = previousWidth >> 2;
When you want to shift a value by a certain number of bits, it's considerably simpler to understand. For example:
byte[] bits = new byte[4];
bits[0] = (byte) (value >> 24);
bits[1] = (byte) (value >> 16);
bits[2] = (byte) (value >> 8);
bits[3] = (byte) (value >> 0);
That's clearly shifting by different numbers of bits. Would you really want to express that in terms of division instead?
Now of course when what you really want is division, you should use the division operator for the sake of readability. Some people may use bitshifting for the sake of performance, but as ever, readability is more important than micro-optimization for most code. So in your case, if what's actually desired is for width to be previousWidth divided by 4, the code should *absolutely reflect that:
int width = previousWidth / 4;
I'd only use bitshifting for this after proving that the performance difference was significant.
Most likely nothing at all. It would be a JVM optimisation to turn a division in to a bitshift.
If it's being done to a bitmask then fine, but if as in the above case it's what appears to be an awkward way of writing a mathematical operation then consider changing it as part of your maintenance (or just accept it as a bad idea but leave it alone).
They are different operations:
>> 2 shifts a bit pattern two bits to the right (essentially dividing an integer by 2^2 = 4).
/ 2 divides the number by two (which could be implemented as >> 1).
Note that using >> 1 to divide other numeric types by 2 is likely to give unexpected results.
If you mean "divide by two", type " / 2". People reading your code (including you, some time later) will thank you for not obscuring the meaning.
As others already said, I suggest you always favor the more readable option over the optimization unless you
definitely need that optimization
know that it works by
knowing your compiler
knowing your JVM
having put performance measurements in place
considering statistic evaluations of those measurements (extrema, variance, first vs. later measurements, ...)

What is the difference between '>>' and ' / ' , shifting and division in java

we can shift using >> operator, and we can use '/' to divide in java. What I am asking is what really happens behind the scene when we do these operations, both are exactly same or not..?
No, absolutely not the same.
You can use >> to divide, yes, but just by 2, because >> shift all the bits to the right with the consequence of dividing by 2 the number.
This is just because of how binary base operations work. And works for unsigned numbers, for signed ones it depends on which codification are you using and what kind of shift it is.
eg.
122 = 01111010 >> 1 = 00111101 = 61
Check this out for an explanation on bit shifting:
What are bitwise shift (bit-shift) operators and how do they work?
Once you understand that, you should understand the difference between that and the division operation.

Categories