Trying to understand crc8. This is my calculations:
poly 100110001 # OneWire
bin 00000001 # 1
1. 000000010 << 1 = 000000100
2. 000000100 << 1 = 000001000
3. 000001000 << 1 = 000010000
4. 000010000 << 1 = 000100000
5. 000100000 << 1 = 001000000
6. 001000000 << 1 = 010000000
7. 010000000 << 1 = 100000000
8. 100000000 ^ 100110001 = 000110001 << 1 = 001100010 == 00110001 # 8 digits
crc8 = 0x31 # online calc true
bin 01000001 # 41
1. 010000010 << 1 = 100000100
2. 100000100 ^ 100110001 = 000110101 << 1 = 001101010
3. 001101010 << 1 = 011010100
4. 011010100 << 1 = 110101000
5. 110101000 ^ 100110001 = 010011001 << 1 = 100110010
6. 100110010 ^ 100110001 = 000000011 << 1 = 000000110
7. 000000110 << 1 = 000001100
8. 000001100 << 1 = 000011000 == 00001100
crc8 = 0xC # online calc true
Now need crc8 of 141 The first one plus the second. Using online calculator https://ghsi.de/CRC/index.php?Polynom=100110001&Message=141 I see that crc8 of 141 must be 0xF8. But 0x31 + 0xC will be 3D. Where is the error?
First off, CRCs don't add like that. You need to take the register value after running 0x01 through, which gives 0x31, and use that as the starting register value when feeding 0x41. You need to exclusive-or the 0x41 with the 0x31 as the first step, resulting in 0x70. Given that, eight steps give you 0xf8 as expected.
However you have not yet arrived at the OneWire CRC-8. That CRC-8 is computed in the reversed direction, shifting down instead of up and using the polynomial (excluding the x8) reversed. Unlike both what you did and what that website does, which is shifting up. What's more, the message is fed in backwards.
Related
I am trying to understand the logic behind the following code which sums 2 integers using bit manipulation:
def sum(a, b):
while b != 0:
carry = a & b
a = a ^ b
b = carry << 1
return a
As an example I used: a = 11 and b = 7
11 in binary representation is 1011
7 in binary representation is 0111
Then I walked through the algorithm:
iter #1: a = 1011, b = 0111
carry = 0011 (3 decimal)
a = 1100 (12 decimal)
b = 0110 (6 decimal)
iter #2: a = 1100, b = 0110
carry = 0100 (4 decimal)
a = 1010 (10 decimal)
b = 1000 (8 decimal)
iter #3: a = 1010, b = 1000
carry = 1000 (8 decimal)
a = 00010 (2 decimal)
b = 10000 (16 decimal)
iter #4: a = 00010, b = 10000
carry = 00000 (0 decimal)
a = 10010 (18 decimal)
b = 00000 (0 decimal)
We Done (because b is now 0).
As we can see, in all iterations a+b is always 18 which is the right answer.
However I failed to understand what is actually happens here. The value of a is going down and down with each iteration until suddenly pops to 18 in the last iteration. Also, can we learn anything from the value of the carry during the process?
I would love to understand the intuition behind this.
Thanks to #WJS answer I think I got it.
let's add 11 and 7 as before, but let's do it in the following order:
First, calculate it without the carry.
Second, calculate only the carry.
Then add both parts.
01011
00111
-----
01100 (neglecting carry)
00110 (finding only the carry)
-----
10010 (sum)
Now, to find the first part, how can we get rid of the carry bits? with XOR.
To find the second part, we use AND and then shift it 1 bit left to place it "under" the right bit.
Now all we have to do is sum both parts. The whole point is not using + operator so how can we do that? Recursion!
We assign the first part to a and the second part to b and we repeat this process until b=0 which means we are done.
Perhaps if you take a simpler example it will help.
a = 11
b = 11
a & b == 11 since AND returns 1's where both bits in the same
position are 1. These are the carry bits.
Now get rid of the the carry locations using exclusive or
a = a ^ b == 00
But a `carry` would cause addition to add bits one position to
the left so shift the carry bits left by 1 bit.
b = carry << 1 = 110
now repeat the process
carry = a & b = 0 & 110 == 0 no more carries
b = carry << 1 == 0
done.
11 + 11 = 110 = 3 + 3 = 6
Understanding the roles of (AND) & and (XOR) ^ are key. Applying those to slightly more complex examples should help. But ignore the interim decimal values as they don't help much. Think only about what is happening in binary.
I think this is easy to understand if you look at what happens with individual bits.
First step is calculating carry which only happens in binary when both bits are 1, so a&b calculates that for every bit. Then bitwise addition is happening via XOR (ignoring carry), and XOR works because:
0+0=0 (==0^0)
1+0=1 (==1^0)
1+1=0 (==1^1, generates carry bit which we ignore)
Next step is to shift carry to the left (<<1), move it to b and repeat until carry is empty.
This statement checks whether a number is 32 bits.
0 < res <= (1 << 31) -1
I can't seem to understand how, can someone help understand this bit shift syntax?
Well, lets begin with an example:
1 in binary is 1
2 in binary is 10
4 in binary is 100
We can see that we need to 'add' an 0 at the end of each number to multiply by 2 and in most language we can do this with this syntax: number << 1
Here we are saying that we add a 1 time a 0 to the left. number >> 1 and here we add 1 time a 0 to the right.
So 1 << 31 means 1 * 2 * 2 * 2 ... 31 times which means 2^31 (so 32 bits)
What I know for A XOR B operation is that the output is 1 if A != B, and 0 if A == B. However, I have no insight about this operation when A and B are not binary.
For example, if A = 1, B = 3, then A XOR B = 2; also, if A = 2, B = 3, then A XOR B = 1. Is there any pattern to the XOR operation for non-binary values?
I have a good understanding of boolean mathematics, so I already understand how XOR works. What I am asking is that how do you, for example, predict the outcome of A XOR B without going through the manual calculation, if A and B are not binaries? Let's pretend that 2 XOR 3 = 1 is not just a mathematical artifact.
Thanks!
Just look at the binary representations of the numbers, and perform the following rules on each bit:
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
So, 1 XOR 3 is:
1 = 001
3 = 011
XOR = 010 = 2
To convert a (decimal) number to binary, repeatedly divide by two until you get to 0, and then the remainders in reverse order is the binary number:
To convert it back, repeatedly subtract it by the largest power of two that's no bigger than it until you get to 0, having each position in the binary number corresponding to the powers you subtracted by set to 1 (the left-most position corresponds to the 0-th power):
(Images reference)
xor on integers and other data is simply xor of the individual bits:
A: 0|0|0|1 = 1
B: 0|0|1|1 = 3
=======
A^B: 0|0|1|0 = 2
^-- Each column is a single bit xor
When you use bit operations on numbers that are more than one bit, it simply performs the operation on each corresponding bit in the inputs, and that becomes the corresponding bit in the output. So:
A = 1 = 00000001
B = 3 = 00000011
--------
result= 00000010 = 2
A = 2 = 00000010
B = 3 = 00000011
--------
result= 00000001 = 1
The result has a 0 bit wherever the input bits were the same, a 1 bit wherever they were different.
You use the same method when performing AND and OR on integers.
I'm writing a program that exchanges the values of the bits on positions 3, 4 and 5 with bits on positions 24, 25 and 26 of a given 32-bit unsigned integer.
So lets say I use the number 15 and I want to turn the 4th bit into a 0, I'd use...
int number = 15
int newnumber = number & (~(1 << 3));
// output is 7
This makes sense because I'm exchanging the 4th bit from 1 to 0 so 15(1111) becomes 7(0111).
However this wont work the other way round (change a 0 to a 1), Now I know how to achieve exchanging a 0 to a 1 via a different method, but I really want to understand the code in this method.
So why wont it work?
The truth table for x AND y is:
x y Output
-----------
0 0 0
0 1 0
1 0 0
1 1 1
In other words, the output/result will only be 1 if both inputs are 1, which means that you cannot change a bit from 0 to 1 through a bitwise AND. Use a bitwise OR for that (e.g. int newnumber = number | (1 << 3);)
To summarize:
Use & ~(1 << n) to clear bit n.
Use | (1 << n) to set bit n.
To set the fourth bit to 0, you AND it with ~(1 << 3) which is the negation of 1000, or 0111.
By the same reasoning, you can set it to 1 by ORing with 1000.
To toggle it, XOR with 1000.
My message bit is 10011010, so code word for this is 0110 and now the codeword is 011100101010.
Suppose the error is in 10th bits and it becomes 011100101110, so finding parity bits:
p1=1+3+5+7+9+11=010111=even number of 1 therefore=0
p2=2+3+6+7+10+11=110111=1
p4=4+5+6+7=1001=0
p8=8+9+10+11+12=01110=1
Comparing with the message the parity is false for 4 and 8 position ie 4+8=12, but in fact we have made errors in 10 bit. Where have I made a mistake?
It works a little bit different. When you check parity, you don't use parity bits to count it (you count them now). So:
p1 = 3+5+7+9+11 = 10111 = 0 (OK)
p2 = 3+6+7+10+11 = 10111 = 0 (WRONG)
p4 = 5+6+7 = 010 = 1 (OK)
p8 = 9+10+11+12 = 1110 = 1 (WRONG)
So 2+8 = 10.