Is it possible to "drop" a couple of most significant bits of a byte number by executing shifting operations in Java?
The idea looks like this:
1010 1111 -> (<<2) -> 1011 1100 -> (>>2) -> 0010 1111 => 2 bits were dropped.
I think the only thing that you're missing from your suggestion is that the right shift should use the unsigned right shift operator, >>>:
int result = (input << n) >>> n;
Related
Java's BitSet class has a method Set that sets a single bit to 1 (=true). The method source code is as follows:
public void set(int bitIndex) {
if (bitIndex < 0)
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
int wordIndex = wordIndex(bitIndex);
expandTo(wordIndex);
words[wordIndex] |= (1L << bitIndex); // Restores invariants
checkInvariants();
}
In addition to the checks, the method's core code is: words[wordIndex] |= (1L << bitIndex). I can clearly see in the assignment that the left part is the specific word that holds the relevant bit. However, I don't understand how the right part (the shifting left of the bit index) cause the setting of the requested (and only it) bit to 1. Could you please explain?
1L << bitIndex produces a long, whose bits are all 0s, except for one of the bits. The position of the "1" bit is determined by bitIndex. For example, if bitIndex is 10, then the 11th least significant bit is 1.
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000
Because the 1 is shifted to the left 10 times. In general, the (bitIndex mod 64 + 1)th least significant bit is the "1" bit.
This mask is then bitwise OR'ed with whatever is in words[wordIndex]. Every bit in words[wordIndex] stays the same because they are OR'ed with 0, except for the one place where it is a "1" in the mask. That bit in words[wordIndex] will become "1" no matter what it was originally, due to how OR works.
There are two parts of interest: 1L << bitIndex and words[wordIndex] |=.
The first part – 1L << bitIndex – shifts a bit some number of spots. Here's a table showing how that plays out with a few different numbers of shifting.
statement
decimal
binary
1L << 0
1
1
1L << 1
2
10
1L << 2
4
100
1L << 3
8
1000
1L << 4
16
10000
The second part – words[wordIndex] |= – takes whatever value was already at words[wordIndex] and uses bitwise "or" to include whatever bit was isolated from above. If that bit was already set (for that word), this operation wouldn't change anything. If the bit was 0, the "or" operation (|=) would set the bit to 1.
Remember that the left side is being ORed (|) with the bit and the right most bit (or the Least Significant Bit - LSB) is bit 0. An OR operator will set the specified one bit(s) in the source, to the same bits in the target, leaving the other bits unchanged. Here are some examples.
int bits = 1;
System.out.println(Integer.toBinaryString(bits));
bits |= 0b100_0000_0000; // set bit 10 to 1.
System.out.println(Integer.toBinaryString(bits));
prints
1
10000000001
^
bit 10
or do it like this
System.out.println(Integer.toBinaryString(bits));
bits = 1;
// or it can be done this way.
bits |= 1<<10; // 10 is the bitIndex in bits to set so it is shifted
// left to that position and the result is as before
System.out.println(Integer.toBinaryString(bits));
prints
10000000001
^
bit 10
I have read here (https://stackoverflow.com/a/27762490/4415632) that when integer overflow occurs, the most significant bits are simply cut off.
However, I have also read here (https://stackoverflow.com/a/27747180/3808877) that when overflow occurs, "the value becomes the minimum value of the type, and start counting up again." Which one is correct, or are both answers correct? If so, can anyone show me why those two interpretations are equivalent to each other?
Both are correct, it depends on context. One is the result of casting and one is the result of overflow. Those are different operations. For example, if you cast Long.MAX_VALUE to an int that is a cast operation
System.out.println((int) Long.MAX_VALUE); // <-- -1
If you overflow an int by adding one to Integer.MAX_VALUE then
System.out.println(Integer.MAX_VALUE + 1); // <-- Integer.MIN_VALUE
Both interpretations are correct, because they are actually the same.
Let's look at the maths to see why.
Java stores values in byte, short, char, int and long in a format called two's complement.
In case of byte, short, int and long it is signed, in case of char it is unsigned.
One of the attributes of the two's complement format is that for most operations it does not matter whether the value is interpreted as signed or unsigned as the resulting bit pattern would be the same.
To shorten things, I'll explain it using byte, but the other types work along the same scheme.
A byte has 8 bits. The topmost bit is interpreted as sign bit. So, the bit pattern goes like this:
snnn nnnn
The separation into two groups of 4 bits each is called Nibble and is performed here for pure readability. As a side note, a nibble can be represented by a hexadecimal digit.
So there are 8 bits in a byte, and each bits could be 0 or 1. This leaves us with 2^8 = 256 different values that could be stored in a byte.
Here are some sample values:
0000 0000 -> 0
0000 0001 -> 1
0000 0010 -> 2
0100 0000 -> 64
0111 1111 -> 127
1000 0000 -> -128
1111 1110 -> -2
1111 1111 -> -1
The 2's complement value of signed numbers which are negative, i.e. the sign bit is set, is created by taking the positive value of the 8 bits and subtracting the range, i.e. in case of a byte by subtracting 256.
Now let's see what happens if you take -1 and add 1.
1111 1111 -1 / 255
+ 0000 0001 1
--------------
= 1 0000 0000 -0 / 256 intermediate result
= 0000 0000 0 / 256 result after dropping excess leading bits
There is an overflow. The result would need 9 bits now, but the byte only has 8 bits, so the most significant bit is lost.
Let's look at another example, -1 plus -1.
1111 1111 -1 / 255
+ 1111 1111 -1 / 255
--------------
= 1 1111 1110 -2 / 510 intermediate result
= 1111 1110 -2 / 254 result after dropping excess leading bits
Or this, 127 plus 5.
0111 1111 127
+ 0000 0101 5
--------------
= 1000 0100 132 / -124
As we can see, the leading bits are dropped and this actually is what leads to the effect that causes it to overflow by "starting to count from the minimum value again".
I add another option: a processor trap. Some processors will generate a trap on integer overflows. When available, this feature usually can be enabled in user mode by setting a bit in the processor status register.
Is there a formula to calculate what the overflow of a Java int would be?
Example: if I add 1 to Integer.MAX_VALUE; the answer is not 2147483648, but rather -2147483648.
Question: if I wanted to calculate what Java would print for a value larger than 2^32, is there an easy mathematical expression (theoretical, not in code)?
((x + 231) mod 232) - 231
Is this what you're looking for? That should be the result of any mathematical operation on a machine that uses 32-bit signed 2's complement integers. That is, if the mathematical value of an operation returns x, the above formula gives the integer that would actually be stored (if the operation doesn't fault, and it's not a "saturating" operation).
Note that I'm using "mod" with a mathematical definition, not the way the % operator works in Java or C. That is, A mod B, where A and B are integers and B > 0, always returns an integer in the range 0 .. B-1, e.g. (-1) mod 5 = 4. More specifically, A mod B = A - B*floor(A/B).
In java an int is 32 bits but it is also signed, which means that the first bit is the "negative" sign. 1 means negative and 0 means positive. Because of this, the largest number is 2147483647 (0111 1111 1111 1111 1111 1111 1111 1111). If you add 1 it makes it 1000 0000 0000 0000 0000 0000 0000 0000 which translates to -2147483648. For any values larger than that you would need to use a long
I believe this would work:
int expected = ((val + Integer.MAX_VALUE) % Integer.MAX_VALUE) - Integer.MAX_VALUE;
This question already has answers here:
What does << mean in Java?
(8 answers)
Closed 8 years ago.
I'm doing an assignment using Java, and our lecturers provided an example code for us. I'm unable to understand some of the code so can anyone explain?
private long magic;
private int minor;
magic = file.readUnsignedShort() << 16 | file.readUnsignedShort();
mnior = file.readUnsignedShort();
I don't understand why did he use "readUnsignedShort" for both of them and why did he add
"<< 16 | file.readUnsignedShort()" for magic. Any help will be much appreciated
A short uses 16 bits, an int uses 32 and a long uses 64 bits.
Given this, there are not unsigned values in Java, so if the most significant bit is 1, it means the value is negative.
Splitting the code you have:
file.readUnsignedShort() <- reads 16 bits
<< 16 <- moves them 16 positions "to the left", adding zeros (it's like multiply by 2^16)
| file.readUnsignedShort(); <- in those 16 zeros, puts the next 16 bites read, using the OR operation, which works as follows:
xxxx0000 | 0000YYYY = xxxxYYYY
Okay, let's start at the beginning.
RandomAccessFile.readUnsignedShort() reads 16 bits of information from the file, without interpreting it as a 2s complement representation.
So in the first line you do this: <first two bytes of the file> << 16 | <third and fourth bytes of the file>
<<16 means shift the number left by 16 bits. For unsigned numbers, this is the equivalent of multiplying by 65536.
| means do a bitwise or. Because we know the first number was shifted, in our case this is equivalent to just adding the numbers.
So this is what it does, why it does it is anybody's guess. You should ask your teacher really, but my guess is that it might have something to do with the fact that this is the only way to read a 32-bit unsigned number via RandomAccessFile.
This operation is like concat for bits.
short is 16 bit and integer is 32 bit long. Concatenating 2 short you will obtain a integer.
The << Operator stands for bitshift, in this way you are shifting the bits by sixteen positions.
Example:
NUMBER1 1111 1111 1111 1111
NUMBER2 0000 0000 0000 0000
NUMBER1 << 16 | NUMBER2 = 1111 1111 1111 1111 0000 0000 0000 0000
(thanks for hints)
magic = file.readUnsignedShort() << 16 | file.readUnsignedShort();
<< is bit shift operation
| is bitwise operation.
Read more here.
I have a Java BigInteger containing two bytes (ex: 1000000100110111). I would like to shift only a single nibble, the right-most nibble in the left byte (in bold below) to the left by one bit:
1000 0001 00110111
Making the result after the shift:
1000 0010 00110111
Any thoughts on the best way to go about doing this?
Thanks,
Chris
If you only want to shift a single bit, you should rather clear the old and set the new:
bigint.clearBit(n-1)
.setBit(n)
If you want to shift those next to four most left bits, you could bitmap them out, shift them, and then or them back:
bigint.and(0xf0ff).or(bigint.and(0x0f00).shiftLeft(1))
Or for clarity:
unshifted = bigint.and(0xf0ff);
shifted = bigint.and(0x0f00).shiftLeft(1);
result = unshifted.or(shifted);
If you don't want 1100 1111 to become 1101 1110 (notice the spill), you can apply the bitmap again on the shifted, before the or.