I know the binary representation of -127 is 10000001 (complement).
Can any body tell me why I right shift it by 1 digit, then I get 11000000 ?
(-127) = 10000001
(-127>>1) = 11000000 ???
Thanks.
If your programming language does a sign-extending right shift (as Java does), then the left-most 1 comes from extending the sign. That is, because the top bit was set in the original number it remains set in the result for each shift (so shifting by more than 1 has all 1's in the top most bits corresponding to the number of shifts done).
This is language dependent - IIRC C and C++ sign-extend on right shift for a signed value and do not for an unsigned value. Java has a special >>> operator to shift without extending (in java all numeric primitive values are signed, including the misleadingly named byte).
Right-shifting in some languages will pad with whatever is in the most significant bit (in this case 1). This is so that the sign will not change on shifting a negative number, which would turn into a positive one if this was not in place.
-127 as a WORD (2 bytes) is 1111111110000001. If you right shift this by 1 bit, and represent it as a single byte the result is 11000000 This is probably what you are seeing.
Because, if you divide -127 (two's-complement encoded as 10000001) by 2 and round down (towards -infinity, not towards zero), you get -64 (two's-complement encoded as 11000000).
Bit-wise, the reason is: when right-shifting signed values, you do sign-extension -- rather than shifting in zeroes, you duplicate the most significant bit. When working with two's-complement signed numbers, this ensures the correct result, as described above.
Assembly languages (and the machine languages they encode) typically have separate instructions for unsigned and signed right-shift operations (also called "logical shift right" vs. "arithmetic shift right"); and compiled languages typically pick the appropriate instruction when shifting unsigned and signed values, respectively.
It's sign extending, so that a negative number right shifted is still a negative number.
Related
I can store numbers ranging from -127 to 127 but other than that it is impossible and the compiler give warning. The binary value of 127 is 01111111, and 130 is 10000010 still the same size (8 bits) and what I think is I can store 130 in Byte but it is not possible. How did that happen?
Java does not have unsigned types, each numeric type in Java is signed (except char but it is not meant for representing numbers but unicode characters).
Let's take a look at byte. It is one byte which is 8 bits. If it would be unsigned, yes, its range would be 0..255.
But if it is signed, it takes 1 bit of information to store the sign (2 possible values: + or -), which leaves us 7 bits to store the numeric (absolute) value. Range of 7 bit information is 0..127.
Note that the representation of signed integer numbers use the 2's complement number format in most languages, Java included.
Note: The range of Java's byte type is actually -128..127. The range -127..127 only contains 255 numbers (not 256 which is the number of all combinations of 8 bits).
In Java, a byte is a signed data type. You are thinking about unsigned bytes, in which case it is possible to store the value 130 in 8 bits. But with a signed data type, that also allows negative numbers, the first bit is necessary to indicate a negative number.
There are two ways to store negative numbers, (one's complement and two's complement) but the most popular one is two's complement. The benefit of it is that for two's complement, most arithmetic operations do not need to take the sign of the number into account; they can work regardless of the sign.
The first bit indicates the sign of the number: When the first bit is 1, then the number is negative. When the first bit is 0, then the number is positive. So you basically only have 7 bits available to store the magnitude of the number. (Using a small trick, this magnitude is shifted by 1 for negative numbers - otherwise, there would be two different bit patterns for "zero", namely 00000000 and 10000000).
When you want to store a number like 130, whose binary representation is 10000010, then it will be interpreted as a negative number, due to the first bit being 1.
Also see http://en.wikipedia.org/wiki/Two%27s_complement , where the trick of how the magnitude is shifted is explained in more detail.
I came across the question "Why is -1 zero fill right shift 1=2147483647 for integers in Java?"
I understood the concept of zero fill right shift perfectly well from the above question's answer. But when I tried to find -1>>1, I am getting a totally complex answer which I felt difficult to understand.
-1 in binary form is as follows: 11111111111111111111111111111111
After flipping the bits, I got: 00000000000000000000000000000000
Upon adding 1 to it, I got: 00000000000000000000000000000001
Now shifting one position right: 00000000000000000000000000000000
After flipping the bits, I got: 11111111111111111111111111111111
Now adding 1 to it: 00000000000000000000000000000000
I don't understand how -1>>1 is -1 itself, then?
When you do a normal right-shift (i.e. using >>, also known as an arithmetic right shift, as opposed to >>>, which is a logical right shift), the number is sign extended.
How this works is as follows:
When we right-shift we get an empty spot in front of the number, like so:
11111111111111111111111111111111
?1111111111111111111111111111111(1) (right-shift it one place)
The last 1 is shifted out, and in comes the ?.
Now, how we fill in the ? is dependent on how we shift.
If we do a logical shift (i.e. >>>), we simply fill it with 0.
If we do a arithmetic shift (i.e. >>), we fill it with the first bit from the original number, i.e. the sign bit (since it's 1 if the number is negative, and 0 if not). This is called sign extension.
So, in this case, -1 >> 1 sign-extends the 1 into the ?, leaving the original -1.
Further reading:
Arithmetic shift on Wikipedia
Logical shift on Wikipedia
>> is a 'signed right shift' operator, so it will preserve the leftmost bit.
So as -1 (dec) is 0xb11111111111111111111111111111111 (bin), right shifting it using >> will preserve the 1 and the result is again 0xb11111111111111111111111111111111 (bin).
For unsigned right shift, the operator >>> can be used. It always fills up with zeroes (0). In your case, -1 >>> 1 results in 0b01111111111111111111111111111111, or 2147483647, which is the largest possible (positive) 32 bit two's complement (and equal to Integer.MAX_VALUE).
In Java, a variable of type int is represented internally as a 32-bit signed integer. Suppose that one bit stores the sign, and the other 31 bits store the magnitude of the number in base 2. In this scheme, what is the largest value that can be stores as type int?
The answer is (2^31)-1. I am curious to what the purpose of the -1 is? Why does 1 have to be subtracted from the magnitude of the number? I don't believe the 1 has anything to do with the sign because that is what the 32nd bit is for.
You are forgetting the 0.
In a decimal system, with a singe digit you are able to store 10 values and largest value is 9 (which is 10^1 - 1).
This is the same story. With a i digits number in base b you are able to store b^i values and the largest one is b^i-1 (I'm ignoring the sign bit right now).
As a side note: the representation used by numbers in Java (as in many other implementations) is the two's complement which has the peculiarity of storing just a 0 (otherwise you would end up having two 0's: -0 and +0 according to the first bit for the sign). So even if the largest value is 2^31-1, the smallest one is -2^31.
You should learn about two's complement notation. All java integer types are signed, and all use this to represent whole numbers. It is very nice, because you never need to subtract.
I have a 3 byte signed number that I need to determine the value of in Java. I believe it is signed with one's complement but I'm not 100% sure (I haven't studied this stuff in more than 10 years and the documentation of my problem isn't super clear). I think the problem I'm having is Java does everything in two's complement. I have a specific example to show:
The original 3-byte number: 0xEE1B17
Parsed as an integer (Integer.parseInt(s, 16)) this becomes: 15604503
If I do a simple bit flip (~) of this I get (I think) a two's complement representation: -15604504
But the value I should be getting is: -1172713
What I think is happening is I'm getting the two's complement of the entire int and not just the 3 bytes of the int, but I don't know how to fix this.
What I have been able to do is convert the integer to a binary string (Integer.toBinaryString()) and then manually "flip" all of the 0s to 1s and vice-versa. When then parsing this integer (Integer.parseInt(s, 16)) I get 1172712 which is very close. In all of the other examples I need to always add 1 to the result to get the answer.
Can anyone diagnose what type of signed number encoding is being used here and if there is a solution other than manually flipping every character of a string? I feel like there must be a much more elegant way to do this.
EDIT: All of the responders have helped in different ways, but my general question was how to flip a 3-byte number and #louis-wasserman answered this and answered first so I'm marking him as the solution. Thanks to everyone for the help!
If you want to flip the low three bytes of a Java int, then you just do ^ 0x00FFFFFF.
0xFFEE1B17 is -1172713
You must only add the leading byte. FF if the highest bit of the 3-byte value is set and 00 otherwise.
A method which converts your 3-byte value to a proper intcould look like this:
if(byte3val>7FFFFF)
return byte3val| 0xFF000000;
else
return byte3val;
Negative signed numbers are defined so that a + (-a) = 0. So it means that all bits are flipped and then 1 added. See Two's complement. You can check that the condition is satisfied by this process by thinking what happens when you add a + ~a + 1.
You can recognize that a number is negative by its most significant bit. So if you need to convert a signed 3-byte number into a 4-byte number, you can do it by checking the bit and if it's set, set also the bits of the fourth byte:
if ((a & 0x800000) != 0)
a = a | 0xff000000;
You can do it also in a single expression, which will most likely perform better, because there is no branching in the computation (branching doesn't play well with pipelining in current CPUs):
a = (0xfffffe << a) >> a;
Here << and >> perform byte shifts. First we shift the number 8 bits to the right (so now it occupies the 3 "upper" bytes instead of the 3 "lower" ones), and then shift it back. The trick is that >> is so-called Arithmetic shift also known as signed shift. copies the most significant bit to all bits that are made vacant by the operation. This is exactly to keep the sign of the number. Indeed:
(0x1ffffe << 8) >> 8 -> 2097150
(0xfffffe << 8) >> 8 -> -2
Just note that java also has a unsigned right shift operator >>>. For more information, see Java Tutorial: Bitwise and Bit Shift Operators.
I have the following division that I need to do often:
int index = pos / 64;
Division can be expensive in the cpu level. I am hoping there is a way to do that with bitwise shift. I would also like to understand how you can go from division to shift, in other words, I don't want to just memorize the bitwise expression.
int index = pos >> 6 will do it, but this is unnecessary. Any reasonable compiler will do this sort of thing for you. Certainly the Sun/Oracle compiler will.
The general rule is that i/(2^n) can be implemented with i >> n. Similarly i*(2^n) is i << n.
You need to be concerned with negative number representation if i is signed. E.g. twos-complement produces reasonable results (if right shift is arithmetic--sign bit copied). Signed magnitude does not.
The compiler will implement it for you in the most efficient way, as long you understand what you need and ask the compiler to do exactly that. If shift is the most efficient way in this case, the compiler will use shift.
Keep in mind though that if you are performing signed division (i.e pos is signed), then it cannot be fully implemented by a shift alone. Shift by itself will generate invalid results for negative values of pos. If the compiler decides to use shifts for this operations, it will also have to perform some post-shift corrections on the intermediate result to make it agree with the requirements of the language specification.
For this reason, if you are really looking for maximum possible efficiency of your division operations, you have to remember not to use signed types thoughtlessly. Prefer to use unsigned types whenever possible, and use signed types only when you have to.
P.S. AFAIK, Java implements Euclidean division, meaning that the above remarks do not apply to Java. Euclidean division is performed correctly by a shift on a negative divisor in 2's-complement representation. The above remarks would apply to C/C++.
http://www.java-samples.com/showtutorial.php?tutorialid=58
For each power of 2 you want to divide by, right shift it once. So to divide by 4 you would right shift twice. To divide by 8 right shift 3 times. Divide by 16 right shift 4 times. 32 -> 5 times. 64 -> 6 times. So to divide by 64 you can right shift 6 times. myvalue = myvalue >> 6;