I need to extract an exact range of bits from an existing long, specifically I need bits 51:12 from a 64 bit value.
The value is:
0x0000000415B2C01E
So the value of bits 51:12 should be:
0x0000415B2C
I'm a bit confused as to how to actually extract that range, or any range for that matter. I've been told to simply left shift by 12 (value << 12) to obtain the bits I need, but that gives me the value of:
0x415B2C01E000
Now I might be completely misunderstanding how bit shifting works, but I can't get my head around how to extract bit ranges. I've found a lot of existing stuff on it, but I'm even more confused about it all now.
If anyone could help me out, it would certainly be appreciated.
Thanks
Shift and mask:
answer = value >> 12 & 0xFFFFFFFFFFF;
Related
Any idea why shift distance for int in java is restricted to 31 bits (5 lower bits of the right hand operand)?
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19
x >>> n
I could see a similar question java Bit operations >>> shift but nobody pointed the right answer
The shift distance is restricted to 31 bits because a Java int has 32 bits. Shifting an int number by more than 32 bits would produce the same value (either 0 or 0xFFFFFFFF, depending on the initial value and the shift operation you use).
It's a design decision, but it seems a bit unfortunate at least for some use cases. First some terminology: let's call the approach of defining as zero all shifts amounts larger than the number of bits in the shifted word the saturating approach, and the Java approach of using only the bottom 5 (or 6 for long) bits to define the shift amount as the mod approach.
You can look at the problem by listing the useful shift values. Those are shift amounts that result in unique output values1. If you take >>>, the interesting values are 0 though 32 inclusive. 0 results in an unchanged value, and 32 results in 0. Shifting by more than 32 would again produce the same result as 32, sure - but java doesn't even let you shift by 32: it stops at 31! A shift by 32 will, perhaps unexpectedly, leave your value unchanged.
In many uses of >>> a shift by 32 is not possible, or the Java behavior works. In other cases, however, the natural result is 32, and you must special case zero.
As to why they would choose that design? Well, it probably helped that the common PC hardware at the time (x86, just like today) implements shifts in exactly that way (using only the last 5 bits for 32-bit shifts, and the last 6 for 64-bits). So the shifts can be directly mapped to hardware without any special cases, conditional moves or branches2.
Furthermore, for hardware that doesn't implement those semantics by default, it is easy to get the Java semantics by a simple mask: shiftAmount & 0x1F. That's going to be fast on all hardware. The reverse mapping - implementing saturating shifts on hardware that doesn't support it is more complex: you may need a costly compare and branch, some bit twiddling hacks or predicated moves to handle the > 31 case.
Finally, the mod approach is quite natural for many algorithms. For example, if you are implementing a bitmap structure, addressable per-bit, a good implementation may be to have an array of integers, with each integer representing 32 bits. Internally to index into the Nth bit, you would break N down into two parts - the high 27 bits would find the word in the array the bit is in, and the low 5 bits would pick the bit out of the word. To pick the bit out of the word (e.g., to move it to the LSB), you might do:
int val = (word >>> (index & 0x1F)) & 1
That sets val to 1 if the bit was set, 0 otherwise. However, because of the way the Java >>> operator was specified, you don't need the & 0x1F part at all, because it is already implied in the mod definition! So you can omit it, and indeed the JDK's BitSet uses exactly that trick.
1 Granted, any value without a 1 in the MSB may not produce unique values under >>>, once all the 1s get shifted off, so let's just talk about any value with a leading one.
2 For what it's worth, I checked ARM and the semantics are even weirder: for variable shifts, the bottom eight bits of the shift amount is used. So the shift is a weird hybrid - it is effectively a saturating shift once you exceed 31, but only up to 255, at which point it loops around and suddenly has non-zero values for the next 31 values, etc.
I have made a variable in java, byte a = 0xA6; //10100110
then I made this :
System.out.println(Integer.toHexString( ((short)a<<8)&0xFFFF ));
The result is 0xA600. This is the right result. But when i tried
System.out.println(Integer.toHexString( ((short)a<<3)&0xFFFF ));
The expected result should be : 0x530 (10100110000)
but I got 0xFD30(1111110100110000) Emm... Can somebody explain how I got that wrong result...??
thanks... :-)
The byte value A6 represents a negative number (bytes are signed in Java). When you cast to a short it gets sign extended to FFA6. Moreover the shift operation is executed with integer values so it is again sign extended to FFFFFFA6. Shift left by three bits gives FFFFFD30 and taking the lower 16 bits gives 0000FD30.
This does not matter if you shift by 8 bits because you shift out and mask the additional 1 bits.
When you declare initialize byte variable you have to downcast it from integer:
byte a = (byte) 0xA6;
So, instead of 10100110 you've got 11111111111111111111111110100110.
And, beacuse of this left shift works in that way:
((short)a<<8)&0xFFFF
returns 1010011000000000
((short)a<<3)&0xFFFF
returns 1111110100110000
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.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have recently started learning java of my own back and I am having trouble with one part in particular. Today I read up on shifting bit values and I was wondering if what I am doing is correct?
I want to shift a value to the right by 16 bits and then clear the upper 24 bits by anding the value with an 8-bit mask of ones. Here is a segment of my code:
int shift(){
point = point >> 16; //shifts the value to the right by 16 bits
point = point & 0xFF; //clear the upper 24 bits
return point;
}
Is this correct? Am I using this technique correctly?
Thanks!
Yes.
some content to fill out the 30 characters minimum length
OK, looks like that joke is not well-received, I was anticipating people to like this satyrical answer. Oh well, apparently people in SO are more serious than I thought.
Well, like others have mentioned, you can actually check it yourself!
As you have written in your code comments, you are already doing it right to convert your comment (human understanding) into code (machine understanding).
How do I know that you're correct? Well, you can check the online resources:
For bit manipulation
Or just this Wikipedia entry
So far your code seems to match your intention, after consulting those resources.
But, you say, that's theoretical, how do I know empirically that my answer is correct?
Well, you can do this method:
Build some sample test cases.
For this case you can use hexadecimal number so that you can easily confirm it (because you can see each bit).
For example: try 0xFFFFFFFF, 0x80000000, 0xC0C0C0C0.
Find the correct answer manually.
In this case, try shifting the bit yourself (using pen and paper)
For 0xFFFFFFFF, which is a 32-bit number with all 1's, when you shift 16 bits to the right you will get 0x0000FFFF, which is a 32-bit number with 1's only at the last 16 bits.
Then you do and AND operation with 0xFF, which is a 32-bit number with 1's only at the last 8 bits. This will again give you 0xFF, since only at the last 8 bits both numbers have bit 1.
Repeat for other examples. You should get 0x00 and 0xC0 for the other example.
Run your code on those input.
To run your code, you can use something called Java compiler (it's usually called javac in most systems).
If you really are a beginner, you can try online compiler like this
Just put your code there and run (with Input/Output (I/O) management, explained here)
Compare your output with the program output.
Usually, this alone will give you confidence that your code is correct.
But sometimes there are tricky cases which make the code incorrect even though it's correct for some small examples. Fortunately we already checked the logic using theoretical answer above.
So I hope that helps!
First let me welcome you to Java. Good choice!
About your question: If this is correct or not depends on what you expect.
But first of all, when learning Java you should do two things:
Get a development environment like Eclipse.
Learn how to write litte test routines with Junit. Here's a JUnit Tutorial
I've taken your code and embedded it in a test routine to see what actually happens:
public class Stackoverflow extends TestCase {
#Test
public final void test() throws IOException {
testNprint(1234);
testNprint(-1234);
testNprint(0);
testNprint(255);
testNprint(256);
testNprint(Integer.MAX_VALUE);
testNprint(Integer.MIN_VALUE);
}
private void testNprint(int point) {
System.out.printf("int: %1$d (0x%1$X) -> shifted: %2$d (0x%2$X)\n",
point, shift(point));
}
private int shift(int point) {
point = point >> 16; //shifts the value to the right by 16 bits
point = point & 0xFF; //clear the upper 24 bits
return point;
}
}
And here's the result. Now you can answer your question: Are the numbers as expected?
int: 1234 (0x4D2) -> shifted: 0 (0x0)
int: -1234 (0xFFFFFB2E) -> shifted: 255 (0xFF)
int: 0 (0x0) -> shifted: 0 (0x0)
int: 255 (0xFF) -> shifted: 0 (0x0)
int: 256 (0x100) -> shifted: 0 (0x0)
int: 2147483647 (0x7FFFFFFF) -> shifted: 255 (0xFF)
int: -2147483648 (0x80000000) -> shifted: 0 (0x0)
BTW: I guess the result is not as you've expected it :-) For the reason find out about the difference of >> and >>>.
Need a solution on how to perform the following: receive a decimal value, convert it to 32-bit Hex, then separate that 32-bit hex and get high 16-bit and low 16-bit values. I have been digging around net and cannot find much info.
Not sure why you are converting to hex but to turn a 32-bit value straight into two 16-bit values.
int x = ...
short high = x >> 16;
short low = x & 0xFFFF;
I expect this is a homework problem. Accordingly, I will give you information that can help you solve it rather than a solution.
Convert the number to hexadecimal. This can be done with the Integer's toHexString() method.
Add enough zeroes to the left to make it eight characters long (8 hexadecimal characters represent 32 bits). You can do this by adding zeroes one by one in a loop until it's 8 characters long, or (better approach) just add 7 zeroes to the left and only deal with the rightmost 8 characters.
Take the the rightmost 4 characters as the lower 16 bits and the 4 characters immediately to the left of that as the higher 16 bits. This can be done with the String's substring() method along with length() and some simple subtraction.
Some APIs you might find useful:
http://download.oracle.com/javase/6/docs/api/java/io/DataInputStream.html
http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html#parseInt(java.lang.String, int)
http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html#toHexString(int)
http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Hex.html