I need to somehow concatenate a series of 8 integers into a single long in Java. The values of the integers are between 0-255. They have to be combined in this manner: Lets say we got this sample of integers (in binary):
00000000 00000000 00000000 11111111
00000000 00000000 00000000 11111101
00000000 00000000 00000000 11110111
00000000 00000000 00000000 10111111
00000000 00000000 00000000 11110011
00000000 00000000 00000000 10111111
00000000 00000000 00000000 01111111
00000000 00000000 00000000 00111111
The resulting float will have to be:
11111111 11111101 11110111 10111111 11110011 10111111 01111111 00111111
Is this somehow achievable in Java?
I have tried using bytes instead of integers but in Java, bytes (and probably every other data type) are signed, so I had to convert them to integers as I can't deal with negative numbers, as I ll need to use them as arguments in another function. I am obligated to try to find a solution this way.
Any help would be appreciated.
You can use a ByteBuffer:
byte[] a = new byte[8];
a[0] = (byte) 255;
a[1] = (byte) 253;
a[2] = (byte) 247;
a[3] = (byte) 191;
a[4] = (byte) 243;
a[5] = (byte) 191;
a[6] = (byte) 127;
a[7] = (byte) 63;
ByteBuffer buffer = ByteBuffer.wrap(a);
System.out.println(buffer.getLong());
// Result:
// 11111111 11111101 11110111 10111111 11110011 10111111 01111111 00111111
Another way to create a ByteBuffer:
ByteBuffer buffer = ByteBuffer.allocate(Byte.SIZE);
buffer.put(0, (byte) 255);
buffer.put(1, (byte) 253);
// ...
buffer.put(7, (byte) 63);
System.out.println(buffer.getLong());
Also, you can use the getLong(...) method implementation separately without creating a ByteBuffer instance:
long result = getLong(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
System.out.println(result);
// Result:
// 11111111 11111101 11110111 10111111 11110011 10111111 01111111 00111111
long getLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) {
return ((((long) b7 ) << 56) |
(((long) b6 & 0xff) << 48) |
(((long) b5 & 0xff) << 40) |
(((long) b4 & 0xff) << 32) |
(((long) b3 & 0xff) << 24) |
(((long) b2 & 0xff) << 16) |
(((long) b1 & 0xff) << 8) |
(((long) b0 & 0xff) ));
}
I would do something like the following:
long result = 0
int[] values = { 1, 2, 3, 4, 5, 6, 7, 8 }
for (int i = 0; i < values.length; i++)
result |= values[i] << i*8;
The |= is a OR and set operator, << is the left shift, and i*8 is the offset in the long.
Here are the building blocks to help you build your own answer:
1) Getting the binary representation of your integer as String:
Integer.toBinaryString(x)
2) Shifting bits pattern x, y bits to the left:
x << y
3) Taking 2 bit patterns x and y of equal length and performing the logical inclusive OR operation:
x | y
4) Getting the binary representation of your long as String:
Long.toBinaryString(x)
Below is a possible solution (with extra methods for displaying the output), based on defined requirements:
public class Integers {
public static void main(String[] args) {
Integers integers = new Integers();
long result = integers.toLong(255, 253, 247, 191, 243, 191, 127, 63);
System.out.println(integers.toBinaryStringWithPadding(result));
}
private long toLong(int... input) {
if (input.length != 8) {
throw new IllegalArgumentException();
}
long result = 0;
for (int i = 0; i < input.length - 1; i++) {
System.out.println(toBinaryStringWithPadding(input[i]) + "\n");
result |= input[i];
result <<= 8;
}
System.out.println(toBinaryStringWithPadding(input.length - 1) + "\n");
result |= input[input.length - 1];
return result;
}
private String toBinaryStringWithPadding(int value) {
String binaryString = Integer.toBinaryString(value);
int padding = 32 - binaryString.length();
StringBuilder tmp = new StringBuilder(32 + 3);
for (int i = 0; i < 32; i++) {
if (i < padding) {
tmp.append('0');
} else {
tmp.append(binaryString.charAt(i - padding));
}
if (i != 0 && (i + 1) % 8 == 0) {
tmp.append(' ');
}
}
return tmp.toString();
}
private String toBinaryStringWithPadding(long value) {
String binaryString = Long.toBinaryString(value);
int padding = 64 - binaryString.length();
StringBuilder tmp = new StringBuilder(64 + 7);
for (int i = 0; i < 64; i++) {
if (i < padding) {
tmp.append('0');
} else {
tmp.append(binaryString.charAt(i - padding));
}
if (i != 0 && (i + 1) % 8 == 0) {
tmp.append(' ');
}
}
return tmp.toString();
}
}
Related
I want to use bitwise operators between strings(stirngs has not the same length) in Java.
Actually, in case that I have two Strings
e.g s1=test s2=sampleJAVA
I convert strngs to binary:
s1Binary=01110100 01100101 01110011 01110100
s2Binary=01110011 01100001 01101101 01110000 01101100 01100101 01001010 01000001 01010110 01000001
And I want to calculate two bitwise operators
s1Binary | s2Binary
s1Binary & s2Binary
I tried for two strings:
String s1 = "test";
byte[] a = s1.getBytes();
String s1Binary = "";
for (int i = 0; i < a.length; i++) {
s1Binary = s1Binary + String.format("%8s", Integer.toBinaryString(a[i] & 0xFF)).replace(' ', '0');
}
/////// s2 /////
String s2 = "sampleJAVA";
byte[] b = s2.getBytes();
String s2Binary = "";
for (int i = 0; i < b.length; i++) {
s2Binary = s2Binary + String.format("%8s", Integer.toBinaryString(b[i] & 0xFF)).replace(' ', '0');
}
But I stuck there because I have two strings with different (binary) length
You can use BigInteger like this.
String s1Binary = "01110100011001010111001101110100";
String s2Binary = "01110011011000010110110101110000011011000110010101001010010000010101011001000001";
BigInteger b1 = new BigInteger(s1Binary, 2);
BigInteger b2 = new BigInteger(s2Binary, 2);
System.out.println(b1.and(b2).toString(2));
System.out.println(b1.or(b2).toString(2));
You can pad the shorter string with leading zeros.
turn 01110100 01100101 01110011 01110100
into 00000000 00000000 00000000 00000000 00000000 00000000 01110100 01100101 01110011 01110100
I'm having trouble calculating the correct CRC value for the 64 bit data stored in a ISO FDX-B complaint microchip. I know the correct CRC should be 0x73f9. Any help would be appreciated.
The raw data is:
Forward LSB - MSB
00010011 10000010 00011100 00101000 01011010 01101111 00000000 00000001
19 130 28 40 90 111 0 1
Reverse MSB - LSB
10000000 00000000 11110110 01011010 00010100 00111000 01000001 11001000
128 0 246 90 20 56 65 200
I feed this into a routine crc16 respectfully;
byte[] y = { (byte)19, (byte)130, (byte)28, (byte)40, (byte)90, (byte)111, (byte)0, (byte)1 };
crc = crc16(y);
// crc = oxa7f0;
byte[] x = { (byte)128, (byte)0, (byte)246, (byte)90, (byte)20, (byte)56, (byte)65 , (byte)200};
int crc = crc16(x);
// crc = 0x1438
Here's the crc routine:
// Calculates the 16 bit CRC value of the byte buffer
public static int crc16(byte[] bytes)
{
int crc = 0x0; // initial value
int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
for (byte b : bytes)
{
for (int i = 0; i < 8; i++)
{
boolean bit = ((b >> (7 - i) & 1) == 1);
boolean c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
if (c15 ^ bit)
crc ^= polynomial;
}
}
crc &= 0xffff;
return crc;
}
With some help from the Arduino community I was able to generate the correct checksum. The algorithm is correct and the solution is to start with an initial value of 0, a poly of 0x1021 and then bit reverse the calculated value. Doing so returns a calculated checksum of 0x9FCE and bit reversing that gives the expected checksum 0x73F9. I have updated the code above.
1001 1111 1100 1110
9 F C E
7 3 F 9
0111 0011 1111 1001
The problem is to reverse the bits of a 32 bit unsigned integer (since Java doesn't have unsigned integers we use long).
Here are two versions of my code. I have two concerns:
(1) why my 1st and 2nd solution don't return the same value (correct or not)
(2) where my 1st and 2nd solution went wrong in not getting the correct answer
//reverse(3) returns 0
public static long reverse(long a) {
long numBits = 32;
long finalResult = 0;
for(int i = 0; i < numBits; i++){
long ithBit = a & (1 << i);
finalResult = finalResult + ithBit * (1 << (numBits - i - 1));
}
return finalResult;
}
Second version:
//reverse(3) return 4294967296
public static long reverse(long a) {
long numBits = 32L;
long finalResult = 0L;
for(long i = 0L; i < numBits; i++){
long ithBit = a & (1L << i);
finalResult = finalResult + ithBit * (1L << (numBits - i - 1L));
}
return finalResult;
}
This code (the solution) returns the correct answer, however:
//reverse(3) returns 3221225472
public static long reverse(long A) {
long rev = 0;
for (int i = 0; i < 32; i++) {
rev <<= 1;
if ((A & (1 << i)) != 0)
rev |= 1;
}
return rev;
}
Thanks!
Let's have a look at your values as you iterate. For clarification, we'll have a look at the intermediate values, so we'll change code to:
int n = (1 << (numBits - i - 1));
long m = ithBit * n;
finalResult = finalResult + m;
Your starting value is 3:
a = 0000 0000 0000 0000 0000 0000 0000 0011
First loop iteration (i = 0):
ithBit = 00000000 00000000 00000000 00000001
n = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
m = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
finalResult = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
Second loop iteration (i = 1):
ithBit = 00000000 00000000 00000000 00000010
n = 01000000 00000000 00000000 00000000
m = 10000000 00000000 00000000 00000000
finalResult = 00000000 00000000 00000000 00000000
As you can see, the first iterate sets n = 1 << 31, which is -2147483648. In your second version you do n = 1L << 31, which is 2147483648, and that's why your two versions give different results.
As you can also see, you definitely don't want to do the m = ithBit * n part.
Have a look at your number by printing them yourself, and you'll figure it out.
BTW, here's my version. If you have trouble understanding it, try printing the intermediate values to see what's going on.
public static long reverse4(long a) {
long rev = 0;
for (int i = 0; i < 32; i++, a >>= 1)
rev = (rev << 1) | (a & 1);
return rev;
}
since Java doesn't have unsigned integers we use long.
That's generally unecessary since all arithmetic operations except division and comparison result in identical bit patterns for unsigned and signed numbers in two's complement representation, which java uses. And for the latter two ops Integer.divideUnsigned(int, int) and Integer.compareUnsigned(int, int) are available.
The problem is to reverse the bits of a 32 bit unsigned integer
There's Integer.reverse(int)
Relevant docs, spending some time reading them is highly recommended.
Problem with your both examples is that the "i-th bit" isn't a 0 or 1 but rather masked off. In either case, the 31'th bit is 0x8000_0000. In the first case, this is an int, so it is negative, and when converted to a long it stays negative. In the second case it is already a long, so it stays positive. To fix it so it does what you intended, do:
ithBit = (a >>> i) & 1;
By the way, using long is silly; unsigned vs. signed makes no difference as long as you understand that there are two types of shifts in Java.
By the way, all three examples are terrible. If you are doing bit manipulation, you want speed, right? (Why else bother with bits?)
This is how to do it right (not mine, stolen from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits):
a = ((a >>> 1) & 0x55555555) | ((a & 0x55555555) << 1);
a = ((a >>> 2) & 0x33333333) | ((a & 0x33333333) << 2);
a = ((a >>> 4) & 0x0F0F0F0F) | ((a & 0x0F0F0F0F) << 4);
a = ((a >>> 8) & 0x00FF00FF) | ((a & 0x00FF00FF) << 8);
a = ( a >>> 16 ) | ( a << 16);
In both versions you have a logic problem here:
ithBit * (1 << (numBits - i - 1));
because the two numbers multiply to the same bit pattern of bit 31 (the 32nd) being set.
In version 1, the amount added is -2^31 if bit 0 is set because you're bit-shifting an int so the bit-shifted result is int which represents -2^31 as the high bit being set, or 2^31 for every other bit, which is possible due to the auto-cast to long of the result. You have two of each kind of bit (0 and non 0) so the result is zero.
Version 2 has the same problem, but without the negative int issue because you're bit shifting a long. Each bit that is 1 will add 2^31. The number 3 has 2 bits set, so your result is 2 * 2^31 (or 2^32) which is 4294967296.
To fix your logic, use version 2 but remove the multiply by ithBit.
No matter how I toss and turn the bytes & bits, I just cannot get this to work. I understand endianess quite ok, and MSB (most significant bit) on some degree. But I'm not able to put the two together it seems.
Currently I have the data in an ordinary JAVA byte[] array. Symbols within the bit stream are encoded using 32-bit little-endian most-to-least-significant bit packing. And I need to read it in a kind of bit reader N bits a time like:
public int read(int bits, boolean advanceReader)
Of course keeping track of the
private int byteOffset;
private int bitOffset;
The issue is getting the values as integers, this I just can't comprehend how to achieve correctly :(
Edit: I'm trying with this Apache Licensed BitReader class with added little endian (I added on to the readInt()) support (original code: https://raw.githubusercontent.com/jcodec/jcodec/master/src/main/java/org/jcodec/common/io/BitReader.java):
public class BitReader {
protected int deficit;
protected int curInt;
private ByteBuffer bb;
private int initPos;
public BitReader(ByteBuffer bb) {
this.bb = bb;
initPos = bb.position();
curInt = readInt();
deficit = 0;
}
public final int readInt() {
if (bb.remaining() >= 4) {
deficit -= 32;
final int b1 = bb.get() & 0xff;
final int b2 = bb.get() & 0xff;
final int b3 = bb.get() & 0xff;
final int b4 = bb.get() & 0xff;
if (bb.order() == ByteOrder.BIG_ENDIAN) {
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
} else {
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
}
} else {
return readIntSafe();
}
}
public int readNBit(int n) {
if (n > 32) {
throw new IllegalArgumentException("Can not read more then 32 bit");
}
int nn = n;
int ret = 0;
if (n + deficit > 31) {
ret |= (curInt >>> deficit);
n -= 32 - deficit;
ret <<= n;
deficit = 32;
curInt = readInt();
}
if (n != 0) {
ret |= curInt >>> (32 - n);
curInt <<= n;
deficit += n;
}
// for(--nn; nn >=0; nn--)
// System.out.print((ret >> nn) & 1);
// System.out.println();
return ret;
}
public int position() {
return ((bb.position() - initPos - 4) << 3) + deficit;
}
}
Maybe I'm missing something in the readNBit, it still handles like big endian? The results are near there, but not quite correct.
Some data:
The array:
[ 0] byte 64
[ 1] byte 1
[ 2] byte -32
[ 3] byte 1
[ 4] byte 100
[ 5] byte 20
[ 6] byte 30
[ 7] byte 3
[ 8] byte 47
[ 9] byte -91
[10] byte 52
[11] byte -12
[12] byte 2
[13] byte -6
[14] byte 11
[15] byte -24
[16] byte 41
[17] byte 98
[18] byte -124
[19] byte 52
Deficit = 21
Position (byte array) = 12
Reading 32 bits gets me: -1510145665
Should be apparently: -1510145696
byte[] array = {
64, 1, -32, 1,
100, 20, 30, 3,
47, -91, 52, -12,
2, -6, 11, -24,
41, 98, -124, 52
};
ByteBuffer bArray = ByteBuffer.wrap(array);
bArray.order(ByteOrder.LITTLE_ENDIAN);
BitReader bitReader = new BitReader(bArray);
bitReader.readNBit(32);
bitReader.readNBit(32);
bitReader.readNBit(21);
int luku = bitReader.readNBit(32);
Luku == -1510145665, and I think it should be -1510145696.
47, -91, 52, -12 to little endian int => 11110100001101001010010100101111
2, -6, 11, -24 to little endian int => 11101000000010111111101000000010
After consuming 21 bits, the following 32 bits 10100101111111010000000101111111 which is 0xA5FD017F in hex and 2784821631 in decimal.
System.out.println(0xA5FD017F);
long l = 2784821631L;
System.out.println((int)l);
will both give you -1510145665. So the original code is correct.
Your changes to take the input byte array as little endian may not what you want when you are reading less than 32 bits at a time. You may have to read one byte at a time instead of using the existing readInt()
This question already has answers here:
Difference between >>> and >>
(9 answers)
Java >>> Operator [duplicate]
(3 answers)
Closed 9 years ago.
I found this code to find duplicates in SO post here.
but I dont understand what this line means int mid = (low + high) >>> 1;
private static int findDuplicate(int[] array) {
int low = 0;
int high = array.length - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
System.out.println(mid);
int midVal = array[mid];
if (midVal == mid)
low = mid + 1;
else
high = mid - 1;
}
return high;
}
The >>> operator is the unsigned right bit-shift operator in Java. It effectively divides the operand by 2 to the power of the right operand, or just 2 here.
The difference between >> and >>> would only show up when shifting negative numbers. The >> operator shifts a 1 bit into the most significant bit if it was a 1, and the >>> shifts in a 0 regardless.
UPDATE:
Let's average 1 and 2147483647 (Integer.MAX_VALUE). We can do the math easily:
(1 + 2147483647) / 2 = 2147483648 / 2 = 1073741824
Now, with the code (low + high) / 2, these are the bits involved:
1: 00000000 00000000 00000000 00000001
+2147483647: 01111111 11111111 11111111 11111111
================================================
-2147483648: 10000000 00000000 00000000 00000000 // Overflow
/2
================================================
-1073741824: 11000000 00000000 00000000 00000000 // Signed divide, same as >> 1.
Let's make the "shift" to >>>:
1: 00000000 00000000 00000000 00000001
+2147483647: 01111111 11111111 11111111 11111111
================================================
-2147483648: 10000000 00000000 00000000 00000000 // Overflow
>>> 1
================================================
+1073741824: 01000000 00000000 00000000 00000000 // Unsigned shift right.
The significance of
int mid = (low + high) >>> 1;
is; by using the unsigned shift, it avoids overflows which result in a negative number. This is needed as Java doesn't support unsigned int values. (BTW char is unsigned)
The traditional way to write this was
int mid = (low + high) / 2; // don't do this
however this could overflow for larger sums and you get a negative number for the mid.
e.g.
int high = 2100000000;
int low = 2000000000;
System.out.println("mid using >>> 1 = " + ((low + high) >>> 1));
System.out.println("mid using / 2 = " + ((low + high) / 2));
prints
mid using >>> 1 = 2050000000
mid using / 2 = -97483648
clearly the second result is incorrect.
its a bitwise operator .. It works on the bit value .
Suppose if A holds 60 then A>>>2 will give 15 (bit value 0000 1111)
Its actual name is "Shift Zero right Operator"
here the left operands value is moved right by the number of bits specified (2 in this case) by the right operand and shifted values are filled up with zeros(0000).