How to Calculate CRC-CCITT from ISO FDX-B microchip data - java

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

Related

Combine integers into a long

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();
}
}

Unique hash with maximum of 4 characters?

What is the best method to create a hash of String, if the hash may not have more than 4 characters, and those 4 characters may only be lowercase letters or digits?
The strings I want to hash have 1-255 characters.
I know that it's probably impossible to create as 4-char hash without collision. But it would be sufficient if I'd have a good hash where possible collisions are minimized.
What I tried is the CRC16CCITT from here:
http://introcs.cs.princeton.edu/java/61data/CRC16CCITT.java
public class CRC16CCITT {
public static void main(String[] args) {
int crc = 0xFFFF; // initial value
int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
// byte[] testBytes = "123456789".getBytes("ASCII");
byte[] bytes = args[0].getBytes();
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;
StdOut.println("CRC16-CCITT = " + Integer.toHexString(crc));
}
}
But this gives too many collision. Are there better algorithms?
You are mistaking "hexadecimal digits" for "characters":
int crc = 0xFFFF; // initial value
That's only 2 bytes (0xFF is just 1 byte). For a CRC of 4 ANSI characters, you need 4 bytes (0xFFFFFFFF).
You'll have to adapt the rest of the code to work with double the legth, please comment if you don't know how to do that.
PS: You could do it with less than 4 bytes, but that would complicate things more than necessary.

Reverse bits of a 32 bit unsigned integer

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.

What does ">>" mean in Java? [duplicate]

I have this statement:
Assume the bit value of byte x is 00101011. what is the result of x>>2?
How can I program it and can someone explain me what is doing?
Firstly, you can not shift a byte in java, you can only shift an int or a long. So the byte will undergo promotion first, e.g.
00101011 -> 00000000000000000000000000101011
or
11010100 -> 11111111111111111111111111010100
Now, x >> N means (if you view it as a string of binary digits):
The rightmost N bits are discarded
The leftmost bit is replicated as many times as necessary to pad the result to the original size (32 or 64 bits), e.g.
00000000000000000000000000101011 >> 2 -> 00000000000000000000000000001010
11111111111111111111111111010100 >> 2 -> 11111111111111111111111111110101
The binary 32 bits for 00101011 is
00000000 00000000 00000000 00101011, and the result is:
00000000 00000000 00000000 00101011 >> 2(times)
\\ \\
00000000 00000000 00000000 00001010
Shifts the bits of 43 to right by distance 2; fills with highest(sign) bit on the left side.
Result is 00001010 with decimal value 10.
00001010
8+2 = 10
When you shift right 2 bits you drop the 2 least significant bits. So:
x = 00101011
x >> 2
// now (notice the 2 new 0's on the left of the byte)
x = 00001010
This is essentially the same thing as dividing an int by 2, 2 times.
In Java
byte b = (byte) 16;
b = b >> 2;
// prints 4
System.out.println(b);
These examples cover the three types of shifts applied to both a positive and a negative number:
// Signed left shift on 626348975
00100101010101010101001110101111 is 626348975
01001010101010101010011101011110 is 1252697950 after << 1
10010101010101010100111010111100 is -1789571396 after << 2
00101010101010101001110101111000 is 715824504 after << 3
// Signed left shift on -552270512
11011111000101010000010101010000 is -552270512
10111110001010100000101010100000 is -1104541024 after << 1
01111100010101000001010101000000 is 2085885248 after << 2
11111000101010000010101010000000 is -123196800 after << 3
// Signed right shift on 626348975
00100101010101010101001110101111 is 626348975
00010010101010101010100111010111 is 313174487 after >> 1
00001001010101010101010011101011 is 156587243 after >> 2
00000100101010101010101001110101 is 78293621 after >> 3
// Signed right shift on -552270512
11011111000101010000010101010000 is -552270512
11101111100010101000001010101000 is -276135256 after >> 1
11110111110001010100000101010100 is -138067628 after >> 2
11111011111000101010000010101010 is -69033814 after >> 3
// Unsigned right shift on 626348975
00100101010101010101001110101111 is 626348975
00010010101010101010100111010111 is 313174487 after >>> 1
00001001010101010101010011101011 is 156587243 after >>> 2
00000100101010101010101001110101 is 78293621 after >>> 3
// Unsigned right shift on -552270512
11011111000101010000010101010000 is -552270512
01101111100010101000001010101000 is 1871348392 after >>> 1
00110111110001010100000101010100 is 935674196 after >>> 2
00011011111000101010000010101010 is 467837098 after >>> 3
>> is the Arithmetic Right Shift operator. All of the bits in the first operand are shifted the number of places indicated by the second operand. The leftmost bits in the result are set to the same value as the leftmost bit in the original number. (This is so that negative numbers remain negative.)
Here's your specific case:
00101011
001010 <-- Shifted twice to the right (rightmost bits dropped)
00001010 <-- Leftmost bits filled with 0s (to match leftmost bit in original number)
public class Shift {
public static void main(String[] args) {
Byte b = Byte.parseByte("00101011",2);
System.out.println(b);
byte val = b.byteValue();
Byte shifted = new Byte((byte) (val >> 2));
System.out.println(shifted);
// often overloked are the methods of Integer
int i = Integer.parseInt("00101011",2);
System.out.println( Integer.toBinaryString(i));
i >>= 2;
System.out.println( Integer.toBinaryString(i));
}
}
Output:
43
10
101011
1010
byte x = 51; //00101011
byte y = (byte) (x >> 2); //00001010 aka Base(10) 10
You can't write binary literals like 00101011 in Java so you can write it in hexadecimal instead:
byte x = 0x2b;
To calculate the result of x >> 2 you can then just write exactly that and print the result.
System.out.println(x >> 2);
You can use e.g. this API if you would like to see bitString presentation of your numbers. Uncommons Math
Example (in jruby)
bitString = org.uncommons.maths.binary.BitString.new(java.math.BigInteger.new("12").toString(2))
bitString.setBit(1, true)
bitString.toNumber => 14
edit: Changed api link and add a little example
00101011 = 43 in decimal
class test {
public static void main(String[] args){
int a= 43;
String b= Integer.toBinaryString(a >> 2);
System.out.println(b);
}
}
Output:
101011 becomes 1010

Byte -> Primitive inconsistency, attempting to create a buffer

I'm attempting to make a customized buffer that's going to be using a List<Byte> and currently I've only gotten as far as a single method before it completely broke down on me, and I'm not sure exactly why. I've been referencing the Source code of the DataOutputStream and DataInputStream classes to make sure that I'm reading/writing the data correctly.
I must be doing something wrong.
private List<Byte> buffer = new ArrayList<>();
public void writeInt(int value) {
buffer.add((byte)((value >>> 24) & 0xFF));
buffer.add((byte)((value >>> 16) & 0xFF));
buffer.add((byte)((value >>> 8) & 0xFF));
buffer.add((byte)((value >>> 0) & 0xFF));
}
public void readInt() {
int ch1 = buffer.get(0);
int ch2 = buffer.get(1);
int ch3 = buffer.get(2);
int ch4 = buffer.get(3);
System.out.println("CH1: " + ch1);
System.out.println("CH2: " + ch2);
System.out.println("CH3: " + ch3);
System.out.println("CH4: " + ch4);
System.out.println("===============");
int value = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
System.out.println("Value: " + value);
}
If I write a small value(Anything from 0->127), it's perfectly fine, however the moment I get to 128, all hell breaks lose, here's the output of 127vs128
#writeInt(127)
CH1: 0
CH2: 0
CH3: 0
CH4: 127
===============
Value: 127
#writeInt(128)
CH1: 0
CH2: 0
CH3: 0
CH4: -128
===============
Value: 128
And just for some more (I don't understand it) examples, here's a large number.
#writeInt(999999999)
CH1: 59
CH2: -102
CH3: -55
CH4: -1
===============
Value: 983156991
I'm honestly not sure where I'm going wrong, hopefully someone can tell me.
EDIT: I also thought it could be because I'm getting the byte as an int, and then trying to do the math, so I changed it up, but it didn't change the result at all. Modification example:
public void readInt() {
int ch1 = buffer.get(0) << 24;
int ch2 = buffer.get(1) << 16;
int ch3 = buffer.get(2) << 8;
int ch4 = buffer.get(3) << 0;
System.out.println("CH1: " + ch1);
System.out.println("CH2: " + ch2);
System.out.println("CH3: " + ch3);
System.out.println("CH4: " + ch4);
System.out.println("===============");
int value = (ch1 + ch2 + ch3 + ch4);
System.out.println("Value: " + value);
}
The type byte in Java is signed, like all primitive types with number semantics (char is the sole exception, but I wouldn't call char number semantics anyway). And Java, like the vast majority of devices, uses two's complement to store values.
Therefore the value range of byte is -128 to 127, here's a few of the corresponding 2's complement bit patterns that would be stored in a byte:
-128 -> 1000 0000
-127 -> 1000 0001
-2 -> 1111 1110
-1 -> 1111 1111
0 -> 0000 0000
1 -> 0000 0001
126 -> 0111 1110
127 -> 0111 1111
When you cast byte to int, and that's what happens implicitly when you do buffer.get() because you do arithmetic with the return value, it happens in a sign-extending way - that's how it's defined in Java.
In other words:
(int) 128 -> 128 (0000 0000 0000 0000 0000 0000 1000 0000)
(byte) (int) 128 -> -128 (---- ---- ---- ---- ---- ---- 1000 0000)
(int) (byte) (int) 128 -> -128 (1111 1111 1111 1111 1111 1111 1000 0000)
You want to negate the effects of sign-extension explicitly. You can do so by using & 0xFF before you shift the value. The corresponding part of your readInt() method should be like this:
int ch1 = buffer.get(0) & 0xFF;
int ch2 = buffer.get(1) & 0xFF;
int ch3 = buffer.get(2) & 0xFF;
int ch4 = buffer.get(3) & 0xFF;

Categories

Resources