Java shl and shr filling problem - java

Is there a way to shift left or right without the byte loss, so that the bytes filled are the ones that are beeing taken?
e.g.:10010 shr 2 => 10100
or: 11001 shl 4 => 11100
the loss of information seems quite inconvenient, since you're not supposed to use it for math anyway..
i just want to send packages over the network in different byte order, so shifting back is important to me

What you're trying to do is bitwise rotation which is supported in Java.
public class Binary {
public static void main(String[] args) {
Integer i = 18;
System.out.println(Integer.toBinaryString(i));
i = Integer.rotateRight(i, 2);
System.out.println(Integer.toBinaryString(i));
}
}
This will print out:
10010
10000000000000000000000000000100
The 2 bits which were shifted off have been rotated round to the start. However there is a lot of 0 padding in the middle because an integer in Java takes up 32 bits.
If you wanted to implement this behaviour yourself, internally it is implemented as:
public static int rotateLeft(int i, int distance) {
return (i << distance) | (i >>> -distance);
}
And:
public static int rotateRight(int i, int distance) {
return (i >>> distance) | (i << -distance);
}

Related

Java not treating 0xFC as a signed integer?

Just when I though I had a fair grasp on how Java treats all Integers/Bytes etc.. as signed numbers, it hit me with another curve ball and got me thinking if I really understand this treatment after all.
This is a piece of assembly code that is supposed to jump to an address if a condition is met (which indeed is met). PC just before the jump is C838h and then after condition check it is supposed to be: C838h + FCh (h = hex) which I thought would be treated as signed so the PC would jump backwards: FCh = -4 in two's compliment negative number. But To my surprise, java ADDED FCh to the PC making it incorrectly jump to C934h instead of back to C834h.
C832: LD B,04 06 0004 (PC=C834)
C834: LD (HL), A 77 9800 (PC=C835)
C835: INC L:00 2C 0001 (PC=C836)
C836: JR NZ, n 20 00FC (PC=C934)
I tested this in a java code and indeed the result was the same:
int a = 0xC838;
int b = 0xFC;
int result = a + b;
System.out.printf("%04X\n", result); //prints C934 (incorrect)
To fix this I had to cast FCh into a byte after checking if the first bit is 1, which it is: 11111100
int a = 0xC838;
int b = (byte) 0xFC;
int result = a + b;
System.out.printf("%04X\n", result); //prints C834 (correct)
In short I guess my question is that I thought java would know that FCh is a negative number but that is not the case unless I cast it to a byte. Why? Sorry I know this question is asked many times and I seem to be asking it myself alot.
0xfc is a positive number. If you want a negative number, then write a negative number. -0x4 would do just fine.
But if you want to apply this to non-constant data, you'll need to tell Java that you want it sign-extended in some way.
The core of the problem is that you have a 32-bit signed integer, but you want it treated like an 8-bit signed integer. The easiest way to achieve that would be to just use byte as you did above.
If you really don't want to write byte, you can write (0xfc << 24) >> 24:
class Main
{
public static void main(String[] args)
{
int a = 0xC838;
int b = (0xfc << 24) >> 24;
int result = a + b;
System.out.printf("%04X\n", result);
}
}
(The 24 derives from the difference of the sizes of int (32 bits) and byte (8 bits)).

Difference between output of bitwise operator

For some reason, the following two bitwise operations provide different results yet it seems intuitive that they should provide the same result since the masks used should be the same. What am I missing here? Why would the results of using the two masks vary?
public class BitShiftTest {
private long bitString = -8784238533840732024L ;
private final int MAX_BITS_POSITION = 63 ;
public static void main(String[] args) {
BitShiftTest bst = new BitShiftTest() ;
System.out.printf("Before applying mask: %s\n", Long.toBinaryString(bst.bitString));
System.out.printf("Using Mask 1: %s\n", Long.toBinaryString(bst.clearBitMask(60)));
System.out.printf("Using Mask 2: %s\n", Long.toBinaryString(bst.clearBitMaskAlternative(60)));
}
public long clearBitMask(int position) {
return bitString & ~(1 << position) ;
}
public long clearBitMaskAlternative(int position) {
return bitString & (0x8000000000000000L >>> MAX_BITS_POSITION - position) ;
}
}
The results produced are
Before applying mask: 1000011000011000000111011001100000101000001000000000000010001000
Using Mask 1: 1000011000011000000111011001100000101000001000000000000010001000
Using Mask 2: 0
You are assuming that ~(1<<position) and 0x8000000000000000L >>> MAX_BITS_POSITION - position are equal, but that's not true.
Basically, you're missing a ~ in the alternative case - otherwise it looks as if you're just trying to extract one bit, not just clear it. It should be:
~(0x8000000000000000L >>> MAX_BITS_POSITION - position)
But also, as noted by #RolandIllig 1 << position is actually done in int arithmetic. You're not seeing this in your output because neither the 60th nor 28th bits happen to be set in the long you are masking. 1L << position fixes this.
1 << 63 is of type int and is therefore equal to Integer.MIN_VALUE, since the 1 is shifted out of the number. (In other languages the result would be undefined since you shift by more bits than an int has.
To fix this, use 1L << 63, which operates on long.

How can I extract a particular bit in Java?

I need a specific bit in a byte value stored as int value. My code is as shown below.
private int getBitValue(int byteVal, int bitShift){
byteVal = byteVal << bitShift;
int bit = (int) (byteVal >>>7);
return bit;
}
It is working when I give the bitshift as 1 but when I give the bitshift as 2 and the byteVal as 67(01000011 in binary), I get the value of 'byteVal' as 268 while 'byteVal' should be 3(000011 in binary) after the first line in the method(the left shift). What am I doing wrong here?
For some reason when I try your code I don't get what you get. For your example, if you say byteVal = 0b01000011 and bitShift = 2, then this is what I get:
byteVal = 0b01000011 << 2 = 0b0100001100
bit = (int) (0b0100001100 >>> 7) = (int) (0b010) // redundant cast
returned value: 0b010 == 2
I believe what you intended to do was shift the bit you wanted to the leftmost position, and then shift it all the way to the right to get the bit. However, your code won't do that for a few reasons:
You need to shift left by (variable length - bitShift) to get the desired bit to the place you want. So in this case, what you really want is to shift byteVal left by 6 places, not 2.
int variables are 32 bits wide, not 8. (so you actually want to shift byteVal left by 30 places)
In addition, your question appears to be somewhat contradictory. You state you want a specific bit, yet your example implies you want the bitShift-th least significant bits.
An easier way of getting a specific bit might be to simply shift right as far as you need and then mask with 1: (also, you can't use return with void, but I'm assuming that was a typo)
private int getBitValue(int byteVal, int bitShift) {
byteVal = byteVal >> bitShift; // makes the bitShift-th bit the rightmost bit
// Assumes bit numbers are 0-based (i.e. original rightmost bit is the 0th bit)
return (int) (byteVal & 1) // AND the result with 1, which keeps only the rightmost bit
}
If you want the bitShift-th least significant bits, I believe something like this would work:
private int getNthLSBits(int byteVal, int numBits) {
return byteVal & ((1 << numBits) - 1);
// ((1 << numBits) - 1) gives you numBits ones
// i.e. if numBits = 3, (1 << numBits) - 1 == 0b111
// AND that with byteVal to get the numBits-th least significant bits
}
I'm curious why the answer should be 3 and I think we need more information on what the function should do.
Assuming you want the value of the byteVal's lowest bitShift bits, I'd do the following.
private int getBitValue(int byteVal, int bitShift){
int mask = 1 << bitShift; // mask = 1000.... (number of 0's = bitShift)
mask--; // mask = 000011111 (number of 1's = bitShift)
return (byteVal & mask);
}
At the very least, this function will return 1 for getBitValue(67, 1) and 3 for getBitValue(67,2).

f(int x) { return x == 0 ? 0 : 1; } in Java without conditionals

I want to implement f(int x) { return x == 0 ? 0 : 1; } in Java.
In C, I'd just "return !!x;", but ! doesn't work like that in Java. Is there some way to do it without conditionals? Without something cheesy like an unrolled version of
int ret = 0;
for (int i = 0; i < 32; i++) {
ret |= ((x & (1 << i)) >>> i);
}
or
try {
return x/x;
} catch (ArithmeticException e) {
return 0;
}
)
EDIT:
So, I did a microbenchmark of three different solutions:
my return x/x catch solution,
the obvious x==0?0:1 solution, and
Ed Staub's solution: (x|-x) >>> 31.
The timings for random int inputs (the whole int range) were:
1. 0.268716
2. 0.324449
3. 0.347852
Yes, my stupid x/x solution was faster by a pretty hefty margin. Not very surprising when you consider that there are very few 0's in it, and in the vast majority of cases the fast path is taken.
The timings for the more interesting case where 50% of inputs are 0:
1. 1.256533
2. 0.321485
3. 0.348999
The naive x==0?0:1 solution was faster by about 5% than the clever one (on my machine). I'll try to do some disassembly tomorrow to find out why.
EDIT2:
Ok, so the disassembly for the conditional version is (excluding book-keeping):
testl rsi,rsi
setnz rax
movzbl rax,rax
The disassembly for (x|-x)>>>31 is:
movl rax,rsi
negl rax
orl rax,rsi
sarl rax,#31
I don't think anything else needs to be said.
Ok, shortest solution without conditional is probably:
return (i|-i) >>> 31;
Here is a solution:
public static int compute(int i)
{
return ((i | (~i + 1)) >> 31) & 1; // return ((i | -i) >> 31) & 1
}
EDIT:
or you can make it more simple:
public static int compute(int i)
{
return -(-i >> 31); // return -i >>> 31
}
EDIT2:
last solution fails with negative numbers. Take a look at #Ed Staub's solution.
EDIT3:
#Orion Adrian OK, here is a general solution:
public static int compute(int i)
{
return (i|-i) >>> java.math.BigInteger.valueOf(Integer.MAX_VALUE).bitLength();
}
int f(int x) {
return Math.abs(Integer.signum(x));
}
The signum() function returns the sign of the number as -1, 0 or 1. So all what's left is to turn -1 into 1, which is what abs does.
The signum function implements it this way
return (i >> 31) | (-i >>> 31);
so, just add another bitwise operation to return 0 or 1
return ((i >> 31) | (-i >>> 31)) & 1;
All of these solutions seem to suffer from the vice of taking varying degrees of effort to understand. That means the programmer who must later read and maintain this code will have to expend unnecessary effort. That costs money.
The expression
(x == 0)? 0:1
is straightforward and simple to understand. It's really the right way to do this. The use of an exception in the ordinary run of code is downright ghastly. Exceptions are for handling circumstances beyond programmer control, not for ordinary routine operations.
I wonder what the compiler would turn this into...
class kata {
public static int f(int x){
return -(Boolean.valueOf(x==0).compareTo(true));
}
public static void main(String[] args) {
System.out.println(f(0));
System.out.println(f(5));
System.out.println(f(-1));
}
}
http://ideone.com/ssAVo
This question reduces down to: "Is there a way to map boolean true,false to int 1,0 respectively without writing the conditional."
In Java, there is no standardized treatment of true as 1. The closest is use of -1. So as #Ed says, the ternary operator is as succinct as you get.
If you wanted a boolean, i think:
return x == x >>> 1
Would do it, because the only number whose set bits don't move when shifted is one with no set bits.
Under the hood, the bytecode actually uses 1 and 0 for true and false, but i don't know of any way to turn a Java language boolean value into its corresponding int value without some sort of conditional.

retrieve value stored in certain bits of an int

We divided an int to save three values into it. For example the first 8 bits (from left to right) hold one value, the 8th to 12th bits hold another value and rest of bits hold the third value.
I am writing a utility method to get value from a certain range of bits of an int. is it good enough? do you have a better solution? The startBitPos and endBitPos are count from right to left.
public static int bitsValue(int intNum, int startBitPos, int endBitPos)
{
//parameters checking ignored for now
int tempValue = intNum << endBitPos;
return tempValue >> (startBitPos + endBitPos);
}
EDIT:
I am sure all values will be unsign.
No, this isn't quite right at the moment:
You should use the unsigned right shift operator to avoid ending up with negative numbers when you don't want them. (That's assuming the original values are unsigned, of course.)
You're not shifting left by the appropriate amount to clear the extraneous high bits.
I suspect you want:
// Clear unnecessary high bits
int tempValue = intNum << (31 - endBitPos);
// Shift back to the lowest bits
return tempValue >>> (31 - endBitPos + startBitPos);
Personally I'd feel more comfortable with a mask-and-shift than this double shifting, but I'm finding it hard to come up with something as short as the above.
public static int bitsValue(int intNum, int startBitPos, int endBitPos)
{
int mask = ~0; //or 0xffffffff
//parameters checking ignored for now
mask = ~(mask<<(endBitPos)) & mask<<startBitPos
return intNum & mask;
}
however if you have commonly used bitranges it's better to keep masks for them statically
0xff000000 // is the 8 most significant bits
0x00e00000 // is the next3 bits and
0x001fffff // are the remaining 21 bits
If you only have a couple of fixed length 'masks' you could store them explicitly and use them like this:
int [] masks = new int [4];
int masks[0] = 0x11111111;
int masks[1] = 0x111100000000;
// ...
public int getValue(int input, int mask){
return input & masks[i];
}

Categories

Resources