Let us start simple. Say you want to find how many 1's in a long in its binary representation. For example, how many 1's in 228₁₀? The binary represenation is 11100100₂. We can use Long.bitCount(228); which returns 4.
Now, let us say we will interpret two bits as a single quaternary digit (and the two far-right bits is the first digit):
00₂ = 0₄
01₂ = 1₄
10₂ = 2₄
11₂ = 3₄
Hence, 228₁₀ = 11100100₂ = 3210₄. The goal is to find how many non-zero quaternary digits are there in the binary representation. For examples, 3210₄ yields 3, 121100₄ yields 4, 000032₄ yields 2, etc.
The code of the Long.bitCount(i); method from Java's documentation is given by:
public static int bitCount(long i) {
i = i - ((i >>> 1) & 0x5555555555555555L);
i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
i = i + (i >>> 8);
i = i + (i >>> 16);
i = i + (i >>> 32);
return (int)i & 0x7f;
}
The goal is to find how many non-zero quaternary digits are there in the binary representation without any types of loops nor the usage of Strings. I am trying to manipulate the code so that it works for quaternary. This is what I currently have:
public static int bitCountQuat(long i) {
i = i - ((i >>> 2) & 0x3333333333333333L);
i = (i & 0x3333333333333333L) + ((i >>> 4) & 0x0f0f0f0f0f0f0f0fL);
i = (i + (i >>> 8)) & 0x00ff00ff00ff00ffL;
i = i + (i >>> 16);
i = i + (i >>> 32);
i = i + (i >>> 64);
return (int) i & 0x7f7f;
}
For more reference: Efficient Implementation of Hamming Weight.
Here are the values from 0 to 9:
Binary, desired output, current output
0000, 0, 0
0001, 1, 2
0010, 1, 4
0011, 1, 6
0100, 1, 6
0101, 2, 0
0110, 2, 2
0111, 2, 4
1000, 1, 4
1001, 2, 6
Start by converting all non-zero quaternary digits to 1s ...
i = (i & 0x5555555555555555L) | ((i >> 1) & 0x5555555555555555L));
... then count the bits in the result.
One way to do that bit count would be to continue from there with
i = (i & 0x3333333333333333L) + ((i >> 2) & 0x3333333333333333L));
i = (i & 0x0f0f0f0f0f0f0f0fL) + ((i >> 4) & 0x0f0f0f0f0f0f0f0fL));
i = (i & 0x00ff00ff00ff00ffL) + ((i >> 8) & 0x00ff00ff00ff00ffL));
i = (i & 0x0000ffff0000ffffL) + ((i >> 16) & 0x0000ffff0000ffffL));
i = (i & 0x00000000ffffffffL) + (i >> 32);
, which are the trailing steps of the implementation presented in the Wikipedia article you referenced.
Alternatively, you could use the (whole) implementation of Long.bitCount(), or even Long.bitCount() itself for the bit counting part. Its variation has enough fewer operations than the (full) Wikipedia version to be about a wash with the above shortcut version.
Related
The below two code is the method can invert the bits of an unsigned 32 bits integer. But What's the difference of the two code below?
Why the first code is wrong and the second code is correct.
I can't see the difference of these two.
public int reverseBits(int n) {
int result = 0;
for (int i = 0; i < 32; i++) {
result = result << 1 | (n & (1 << i));
}
return result;
}
public int reverseBits(int n) {
int result = 0;
for (int i = 0; i < 32; i++) {
result = result << 1 | ((n >> i) & 1);
}
return result;
}
Appreciate any help.
The first code is wrong, because it extracts given bit and puts it in the same position of the resulting number. Suppose you are on iteration i = 5. Then n & (1 << 5) = n & 32 which is either 0 or 0b100000. The intention is to put the one-bit to the lowest position, but when performing | operation it actually puts it to the same position #5. On the consequent iterations you move this bit even higher, so you practically have all the bits or'ed at the highest bit position.
Please note that there are more effective algorithms to reverse bits like one implemented in standard JDK Integer.reverse method:
public static int reverse(int i) {
// HD, Figure 7-1
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
i = (i << 24) | ((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) | (i >>> 24);
return i;
}
It has to do with whether the bit being grabbed from n is being stored in the rightmost bit of the result or being stored back into the same position.
Suppose n is 4 (for example).
Then when i is 2, the expression (n & (1 << i))
becomes (4 & (1 << 2)), which should equal 4 & 4, so it evaluates to 4.
But the expression ((n >> i) & 1)
becomes ((4 >> 2) & 1), which should equal 1 & 1, so it evaluates to 1.
The two expressions do not have the same result.
But both versions of the function try to use those results in the exact same way, so the two versions of the function do not have the same result.
I have a Java CRC16 function like below and I need it to return a 4 length alphanumeric result. But sometimes it returns only a 3 length alphanumeric. Why? I am cross comparing this CRC with a C application that calculates the CRC and usually it is the same CRC but from time to time the JAVA returns a 3 character result which raises an exception. Why?
int crrc = 0xFFFF; // initial value
int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
String str = "0009";
byte []by = x; // x is the byte array from args
for (byte b : by) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7-i) & 1) == 1);
boolean c15 = ((crrc >> 15 & 1) == 1);
crrc <<= 1;
if (c15 ^ bit) crrc ^= polynomial;
}
}
crrc &= 0xffff;
System.out.println(crrc);
System.out.println("CRC16-CCITT = " + Integer.toHexString(crrc) + " " + Integer.toHexString(crrc).length());
You're receiving ArrayIndexOutOfBoundException probably, so I think the hex value might have zero in its most significant nibble. Try to find out those values(x) and check whether (x >>> 12) == 0 or (x & 0xf000) == 0. If this returns true, you can pad your string with necessary number of 0s from the left.
One possible way: String.format("%04d", crrc)
I receive a datapacket containing a byte array and I have to get some integer values from it.
Here is a part of the documentation. Can someone help me please?
This comes in a 4-byte array.
Year from 1990 to 2052 (6 bit), Month from 1 to 12 (4 bit), Day from 1
to 31 (5 bit), Hour from 0 to 23 (5 bit), Minute from 0 to 59 (6 bit),
Second from 0 to 59 (6 bit) Default value: 1 January 2000, 12:00:00
The format of the message is in little endian.
What you need is some bitwise operations. First, construct an int out of the bytes:
int n = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
Then, chop up the int into components. Now, your question does not specify which way do the fields go, right-to-left or left-to-right. That question is related to endianness, but not identical. So let's assume that the fields go from left to right.
Good sense suggests left-to-right. This way the integer representations of time values can be compared - the significance of year bits is more than month bits etc, so when you compare integers that correspond to two moments in time, you get a chronologically correct result.
Here's a mental image for you. This is an integer variable, composed of bits:
f e d c b a 9 8 7 6 5 4 3 2 1 0
-----
offset is 6, length is 3
Let's define a function that takes a arbitrary chunk from an int at a given offset (in bits), with a given length (in bits).
int bits(int n, int offset, int length)
{
//shift the bits rightward, so that the desired chunk is at the right end
n = n >> (31 - offset - length);
//prepare a mask where only the rightmost `length` bits are 1's
int mask = ~(-1 << length);
//zero out all bits but the right chunk
return n & mask;
}
Could've been a one-liner, but I wanted to make it somewhat instructive. Folks in the answers below effectively inline this function, by specifying the shift factor and the mask by hand for each chunk.
Now let's decompose. Assuming n comes from the topmost snippet:
int year = bits(n, 0, 6),
month = bits(n, 6, 4),
day = bits(n, 10, 5),
hour = bits(n, 15, 5),
min = bits(n, 20, 6),
sec = bits(n, 26, 6);
We get the values of the offset by combining the total lengths of the previous fields together. This is under the assumption that the fields go left to right; if they go the other way around, the offset values would be different.
Did that make sense?
EDIT: if the bit chunks go right to leftt, then here's how it'd go:
int sec = bits(n, 0, 6),
min = bits(n, 6, 6),
hour = bits(n, 12, 5),
day = bits(n, 17, 5),
month = bits(n, 22, 4),
year = bits(n, 26, 6);
First, I'd convert this to an integer:
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
int timestamp = ByteBuffer.wrap(byte_array).order(ByteOrder.LITTLE_ENDIAN).getInt();
Next, I'd take it apart:
int yearCode = (timestamp >> 26) & 0b111111;
int monthCode = (timestamp >> 22) & 0b1111;
int dayCode = (timestamp >> 17) & 0b11111;
int hourCode = (timestamp >> 12) & 0b11111;
int minCode = (timestamp >> 6) & 0b111111;
int secCode = (timestamp >> 0) & 0b111111;
The masking in the first line and shifting in the last line are not strictly necessary, but are left in for clarity.
The final step is to add 1900 to the yearCode and you're done!
Assuming you have java 7, you should be able to read the year as
int year = 1990
+ ((b[0] & 0b1000_0000) << 5)
+ ((b[0] & 0b0100_0000) << 4)
+ ((b[0] & 0b0010_0000) << 3)
+ ((b[0] & 0b0001_0000) << 2)
+ ((b[0] & 0b0000_1000) << 1)
+ ((b[0] & 0b0000_0100));
and the month as
int month = 1
+ ((b[0] & 0b1000_0010) << 3)
+ ((b[0] & 0b0100_0001) << 2)
+ ((b[1] & 0b1000_0000) << 1)
+ ((b[1] & 0b0100_0000));
I let you do the others ints in the same way.
I don't have java7 and can't test now, I hope I'm not wrong. It's also possible that the order of the bytes is the reverse one.
There is a method in Java that reverses bits in an Integer reverseBytes(). I wanted to try another implementation and this is what I have:
public static int reverse(int num) {
int num_rev = 0;
for (int i = 0; i < Integer.SIZE; i++) {
System.out.print((num >> i) & 1);
if (((num >> i) & 1)!=0) {
num_rev = num_rev | (int)Math.pow(2, Integer.SIZE-i);
}
}
return num_rev;
}
The result num_rev is not correct. Does anyone have any idea how to "reconstruct" the value? Maybe there is a better way to perform it?
Thanks for any suggestions.
The normal way would to reverse bits would be via bit manipulation, and certainly not via floating point math routines!
e.g (nb: untested).
int reverse(int x) {
int y = 0;
for (int i = 0; i < 32; ++i) {
y <<= 1; // make space
y |= (x & 1); // copy LSB of X into Y
x >>>= 1; // shift X right
}
return y;
}
Because x is right shifted and y left shifted the result is that the original LSB of x eventually becomes the MSB of y.
A nice (and reasonably well known) method is this:
unsigned int reverse(unsigned int x)
{
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
return ((x >> 16) | (x << 16));
}
This is actually C code, but as Java doesn't have unsigned types to port to Java all you should need to do is remove the unsigned qualifiers and use >>> instead of >> to ensure that you don't get any "sign extension".
It works by first swapping every other bit, then every other pair of bits, then every other nybble, then every other byte, and then finally the top and bottom 16-bit words. This actually works :)
There are 2 problems with your code:
You're using an int cast. You should be doing (long)Math.pow(... The problem with int casting is that pow(2, n) will always be a positive number, so pow(2, 31) casted to an int will be rounded to (2^31)-1, because that's the largest positive int. The bit field for 2^31-1 is 0x7ffffff, but in this case you want 0x80000000, which is exactly what the lower 32 bits of the casted long will be.
You're doing pow(2, Integer.Size - i). That should be Integer.SIZE - i - 1. You basically want to take bit 0 to the last bit, bit 1 to the second last and so on. However, the last bit is bit 31, not bit 32. Your code right now is trying to set bit 0 to bit Integer.SIZE-0 == 32, so you need to subtract 1.
The above is assuming this is just for fun. If you really need to reverse bits, however, please don't use floating point ops. Do what some of the another answers suggest.
why you don't want to use:
public static int reverseBytes(int i) {
return ((i >>> 24) ) |
((i >> 8) & 0xFF00) |
((i << 8) & 0xFF0000) |
((i << 24));
}
edited:
Integer has also:
public static int reverse(int i)
Returns the value obtained by
reversing the order of the bits in the
two's complement binary representation
of the specified int value.
I am lookin for a method to have number of 1's in 32 bit number
without using a loop in between.
can any body help me and provide me the code or algorithm
to do so.
Thanks in advance.
See Integer.bitCount(int). You can refer to the source code if you want to see how it works; many of the Integer class's bit twiddling routines are taken from Hacker's Delight.
See the canonical reference: Bit Twiddling Hacks
Short, obscenely optimized answer (in C):
int pop(unsigned x) {
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x >> 8);
x = x + (x >> 16);
return x & 0x0000003F;
}
To see why this magic works, see The Quest for an Accelerated Population Count by Henry S. Warren, Jr. chapter 10 in Beautiful Code.
Split the 32 bit number into four 8 bit numbers (see bit shifting operator, casting etc.)
Then use a lookup with 256 entries that converts the 8 bit number into a count of bits set. Add the four results, presto!
Also, see what Mitch Wheat said - bit fiddling can be a lot of fun ;)
You can define it recursively:
int bitcount(int x) {
return (x==0) ? 0 : (x & 1 + bitcount(x/2));
}
The code above is not tested, and probably only works for x>=0. Hopefully, you will get the idea anyways...
My personal favourite, directly from Bit Twiddling Hacks:
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
Following is JDK 1.5 implementation of of Integer.bitCount
public static int bitCount(int i) {
// HD, Figure 5-2
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}