I have an int and I want to invert the bits of it using the ~ bit operator. This should be a very simply thing to do, however I tried and it doesn't work. I suppose this is because java uses two's complement to represent it's int. So what is the most efficient way to do this? 50 when inverted should be 13 and that's the value I'd like to have
It seems you want only the part of the bitwise complement until the most signifficant set bit of the input. Then you just have to mask the complement,
int invert(int n) {
return ~n & mask(n);
}
int mask(int n) {
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
return n | (n >> 16);
}
Java int is 32-bit long with 1 bit used for sign. Therefore 50 is represented in binary as 00000000000000000000000000110010. If you bit-invert this, you'll get 11111111111111111111111111001101, which is java integer value -51 in decimal notation.
Since an int should be at least 32 bits wide, ~50 is definitely not 13. I think you are assuming the int to be only 8 bits wide, which may have been the case some 237 years ago, but definitely not nowadays and not in Java, anyway. If you need a data type that is guaranteed to be 8 bits wide, use byte.
But even then ~50 is not 13, only if take the least significant 6 bits into account. But all this doesn't have anything to do with two's complement.
Related
I was recently looking into some problems with but manipulation in Java and I came up with two questions.
1) Firstly, I came up to the problem of flipping all the bits in a number.
I found this solution:
public class Solution {
public int flipAllBits(int num) {
int mask = (1 << (int)Math.floor(Math.log(num)/Math.log(2))+1) - 1;
return num ^ mask;
}
}
But what happens when k = 32 bits? Can the 1 be shifted 33 times?
What I understand from the code (although it doesn't really make sense), the mask is 0111111.(31 1's)....1 and not 32 1's, as someone would expect. And therefore when num is a really large number this would fail.
2) Another question I had was determining when something is a bit sequence in 2s complement or just a normal bit sequence. For example I read that 1010 when flipped is 0110 which is -10 but also 6. Which one is it and how do we know?
Thanks.
1) The Math object calls are not necessary. Flipping all the bits in any ordinal type in Java (or C) is not an arithmatic operation. It is a bitwise operation. Using the '^' operator, simply using 1- as an operand will work regardless of the sizeof int in C/C++ or a Java template with with the ordinal type as a parameter T. The tilde '~' operator is the other option.
T i = 0xf0f0f0f0;
System.out.println(T.toHexString(i));
i ^= -1;
System.out.println(T.toHexString(i));
i = ~ i;
System.out.println(T.toHexString(i));
2) Since the entire range of integers maps to the entire range of integers in a 2's compliment transform, it is not possible to detect whether a number is or is not 2's complement unless one knows the range of numbers from which the 2's complement might be calculated and the two sets (before and after) are mutually exclusive.
That mask computation is fairly inscrutable, I'm going to guess that it (attempts to, since you mention it's wrong) make a mask up to and including the highest set bit. Whether that's useful for "flipping all bits" is an other possible point of discussion, since to me at least, "all bits" means all 32 of them, not some number that depends on the value. But if that's what you want then that's what you want. Especially combined with that second question, that looks like a mistake to me, so you'd be implementing the wrong thing from the start - see near the bottom.
Anyway, the mask can be generated with some reasonably nice bitmath, which does not create any doubt about possible edge cases (eg Math.log(0) is probably bad, and k=32 corresponds with negative numbers which are also probably bad to put into a log):
int m = num | (num >> 16);
m |= m >> 8;
m |= m >> 4;
m |= m >> 2;
m |= m >> 1;
return num ^ m;
Note that this function has odd properties, it almost always returns an unsigned-lower number than went in, except at 0. It flips bits so the name is not completely wrong, but flipAllBits(flipAllBits(x)) != x (usually), while the name suggests it should be an involution.
As for the second question, there is nothing to determine. Two's complement is scheme by which you can interpret a bitvector - any bitvector. So it's really a choice you make; to interpret a given bitvector that way or some other way. In Java the "default" interpretation is two's complement (eg toString will print an int by interpreting it according to its two's complement meaning), but you don't have to go along with it, you can (with care) treat int as unsigned, or as an array of booleans, or several bitfields packed together, etc.
If you wanted to invert all the bits but made the common mistake to assume that the number of bits in an int is variable (and that you therefore needed to compute a mask that covers "all bits"), I have some great news for you, because inverting all bits is a lot easier:
return ~num;
If you were reading "invert all bits" in the context of two's complement, it would have the above meaning, so all bits, including those left of the highest set bit.
I recently learned a method in BigInteger Java class called
BigInteger.testBit(n)
Its main function is (this & (1<<n)) != 0), but I do not quite understand the source code
return (getInt(n >>> 5) & (1 << (n & 31))) != 0;
Can someone explain it?
I'm not familiar with how it's implemented, but judging by that code, I would assume that a BigInteger is implemented by storing it's value in a list of integers, and getInt(n) returns the n'th of these, where 0 = least significant.
The first will store the least significant 32 bits, getInt(1) will store bits 32-63 etc. By shifting n right by 5, you get the index of the integer in the internal list that has the bit you care about, it's the equivalent to n div 32.
With that integer, you then pick out the bit you care about from it with the (1 << (n & 31)). n & 31 is the equivalent of n modulo 32, and the 1 << is the equivalent of 2^. This gets you a bit mask that selects precisely the bit you care about.
I want to put a short integer (16 bits) into tail of a 32 bits integer (I'm compressing some small-range numbers to an unique integer). But didn't found a better looking way than bellow, I have to use two operation, can it be better?
short sh = -1; // 16 bits 1
int zip = 0; // last 16 bits presents a short number
System.out.println("Wrong way, maybe many of us will try first:");
zip |= sh; // expect 0xffff
System.out.println(Integer.toHexString(zip)); // but 0xffffffff
System.out.println("Simple way, right but looks ugly, two operations");
zip = 0;
zip |= sh << 16 >>> 16; // expect 0xffff
System.out.println(Integer.toHexString(zip)); // yeah
System.out.println("Is there a nicer looking way, one operation for example?");
All bitwise operations in Java are done using ints or longs, therefore you don't have too much choice here; and casting a shorter primitive type whose sign bit is set will "expand" the sign bit to all "newer created" bits.
There is a solution to do it "in one line", but that will still be two operations:
zip |= (sh & 0xffff);
Note, it pretty much requires that zip is 0 to start with, or at least that its 16 low bits are 0.
I am trying to understand how the following line of code works:
for (int i = 0; i < numSamples; i++) {
short ampValue = 0;
for (int byteNo = 0; byteNo < 2; byteNo++) {
ampValue |= (short) ((data[pointer++] & 0xFF) << (byteNo * 8));
}
amplitudes[i] = ampValue;
}
As far as I understand, this is reading 2 bytes (as 2 bytes per sample) in a inclusive manner, i.e. the ampValue is composed of two byte reads. The data is the actual data sample (file) and the pointer is increasing to read it upto the last sample. But I don't understand this part:
"data[pointer++] & 0xFF) << (byteNo * 8)); "
Also, I am wondering whether it makes any difference if I want to read this as a double instead of short?
Looks like data[] is the array of bytes.
data[pointer++] gives you a byte value in the range [-128..127].
0xFF is an int contstant, so...
data[pointer++] & 0xFF promotes the byte value to an int value in the range [-128..127]. Then the & operator zeroes out all of the bits that are not set in 0xFF (i.e., it zeroes out the 24 upper bits, leaving only the low 8 bits.
The value of that expression now will be in the range [0..255].
The << operator shifts the result to the left by (byteNo * 8) bits. That's the same as saying, it multiplies the value by 2 raised to the power of (byteNo * 8). When byteNo==0, it will multiply by 2 to the power 0 (i.e., it will multiply by 1). When byteNo==1, it will multiply by 2 to the power 8 (i.e., it will multiply by 256).
This loop is creating an int in the range [0..65535] (16 bits) from each pair of bytes in the array, taking the first member of each pair as the low-order byte and the second member as the high-order byte.
It won't work to declare ampValue as double, because the |= operator will not work on a double, but you can declare the amplitudes[] array to be an array of double, and the assignment amplitudes[i] = ampValue will implicitly promote the value to a double value in the range [0.0..65535.0].
Additional info: Don't overlook #KevinKrumwiede's comment about a bug in the example.
In Java, all bytes are signed. The expression (data[pointer++] & 0xFF) converts the signed byte value to an int with the value of the byte if it were unsigned. Then the expression << (byteNo * 8) left-shifts the resulting value by zero or eight bits depending on the value of byteNo. The value of the whole expression is assigned with bitwise or to ampValue.
There appears to be a bug in this code. The value of ampValue is not reset to zero between iterations. And amplitude is not used. Are those identifiers supposed to be the same?
Let's break down the statement:
|= is the bitwise or and assignment operator. a |= b is equivalent to a = a | b.
(short) casts the int element from the data array to a short.
pointer++ is a post-increment operation. The value of pointer will be returned and used and then immediately incremented every single time it's accessed in this fashion - this is beneficial in this case because the outer-loop is cycling through 2-byte samples (via the inner loop) from the contiguous data buffer, so this keeps incrementing.
& is the bitwise AND operator and 0xFF is the hexadecimal value for the byte 0b11111111 (255 in decimal); the expression data[pointer++] & 0xFF is basically saying, for each bit in the byte retrieved from the data array, AND it with 1. In this context, it forces Java, which by default stores signed byte objects (i.e. values from -128 to 127 in decimal), to return the value as an unsigned byte (i.e. values from 0 to 255 decimal).
Since your samples are 2 bytes long, you need to shift the second lot of 8 bits left, as the most significant bits, using the left bit-shift operator <<. The byteNo * 8 ensures that you're only shifting bits when it's the second of the two bytes.
After the two bytes have been read, ampValue will now contain the value of the sample as a short.
This question already has answers here:
java byte data type
(3 answers)
Closed 8 years ago.
since english isn't my main language and i've didn't find any pointers as to how to manually calculate the new number.
Example:
byte b = (byte) 720;
System.out.println(b); // -48
I know that most primary data types use the two complement.
Byte value ranges from -128 to 127, so it's expected to round the number down to something that fits in byte.
The Question is how do i manually calculate the -48 of the typecasted 720? I've read that i have to convert it to two complement, so taking the binary number, searching from right to left for the first one and then inverting all others and since byte only has 8 bits, take the first 8 bits. But that didn't quite work for me, it would be helpful if you would tell me how to calculate a typecasted number that doesn't fit into byte. Thanks for reading! :)
The binary representation of 702 is
10 1101 0000
Get rid of everything except the last 8 bits (because that's what fits into a byte).
1101 0000
Because of the leading 1, get the complement
0010 1111
and add 1
0011 0000
and negate the value. Gives -48.
In Java, integral types are always 2's complement. Section 4.2 of the JLS states:
The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers
You can mask out the least significant 8 bits.
int value = 720;
value &= 0xFF;
But that leaves a number in the range 0-255. Numbers higher than 127 represent negative numbers for bytes.
if (value > Byte.MAX_VALUE)
value -= 1 << 8;
This manually yields the -48 that the (byte) cast yields.
First what happens is the value (in binary) is truncated.
720 binary is 0b1011010000
We can only fit 8 bits 0b11010000
first digit 1, so the value is negative.
2's compliment gives you -48.
This is close to redundant with the answer posted by rgettman, but since you inquired about the two's complement, here is "manually" taking the 2's complement, rather than simply subtracting 256 as in that answer.
To mask the integer down to the bits that will be considered for a byte, combine it bitwise with 11111111.
int i = 720;
int x = i & 0xFF;
Then to take the two's complement:
if (x >> 7 == 1) {
x = -1 * ((x ^ 0xFF) + 1);
}
System.out.println(x);