I have seem the CRC calculation polynomial for CAN 2.0B, but I have no examples to actually make sure I understood how to calculate it.
X15 + X14 + X10 + X8 + X7 + X4 + X3 + 1
I would really appreciate seeing a step by step calculation for such a CRC.
The CAN 2.0 document says exactly how to do it:
CRC_RG = 0 //initialize shift register
REPEAT
CRCNXT = NXTBIT EXOR CRC_RG(14)
CRC_RG(14:1) = CRC_RG(13:0) //shift left by...
CRC_RG(0) = 0 //...one position
IF CRCNXT THEN
CRC_RG(14:0) = CRC_RG(14:0) EXOR (4599 hex)
ENDIF
UNTIL (CRC SEQUENCE starts or there is an ERROR condition)
Note that 4599 in hex is the polynomial, i.e. the bits 14, 10, 8, 7, 4, 3, and 0 are set. (The 15 bit position is what is pulled off after the shift.)
You can find an example here to verify that you're doing it right. This CRC applied to the ASCII string of digits (nine bytes) 123456789 is 0x059e.
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.
I'm working with single variable polynomials with coefficients +1/-1 (and zero). These can be very long and the range of powers can be quite big. It would be convenient for me to view the powers as a vector - is there any way of doing this quickly? I had hoped there would be a command already in Pari to do this, but I can't seem to see one?
Just an example to confirm what I'm trying to do...
Input:x^10 - x^8 + x^5 - x^2 + x + 1
Desired output: [10, 8, 5, 2, 1, 0]
You can use Vecrev to get the polynomial coefficients. After that just enumerate them to select the zero-based positions of non-zeros. You want the following one-liner:
nonzeros(xs) = Vecrev([x[2]-1 | x <- select(x -> x[1] != 0, vector(#xs, i, [xs[i], i]))])
Now you can easily get the list of polynomial powers:
p = x^10 - x^8 + x^5 - x^2 + x + 1
nonzeros(Vecrev(p))
>> [10, 8, 5, 2, 1, 0]
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm struggling with the piece of code below, it's used to convert an integer into a binary. Can someone explain it more cearly? especially the '0'+
for (;d>0;d--){
buffer[index++] = '0'+ (x & 1);
x >>= 1;
}
First of all, "index" is initialized to 0. But what is the definition of "d"?
We have an array of characters named "buffer" and "x" is an integer to be converted.
Now, in "x & 1", "&" is Bitwise AND operator. If we operate "x & n", it changes the last n least significant bits as,
1 & 1 = 1,
1 & 0 = 0,
0 & 1 = 0,
0 & 0 = 0.
if we execute 4 & 1,
100
001
---
000
then, it returns 0.
if we execute 9 & 1,
1001
0001
----
0001
then, it returns 1.
Basically, if x is a even number x&1 returns 0, or returns 1 if x is odd.
Now, after that, this 0 or 1 is added to '0' (ascii 48), which is-
if x is even, '0' + (x & 1) stays '0', otherwise it becomes '1' as x&1 returns 1 and '0'+1 is '1'.
After that in "x >>= 1", ">>" is Bitwise right shift operator, which is equivalent to x = x / 2 or x /= 2. But there is little bit difference if we consider integers.
Consider x = 12, that is 1100 in binary.
if we execute x >>= 1, then x becomes 6, if shifts away last 0 of 1100, becomes 110.
again if we execute x >>= 1, then x becomes 3, if shifts away last 0 of 110, becomes 11.
again if we execute x >>= 1, then x becomes 1, if shifts away last 1 of 11, becomes 1.
again if we execute x >>= 1, then x becomes 0, if shifts away last 1 of 1, becomes 0.
Finally, if x is even it stores '0' in buffer[index], otherwise stores '1', until x is not 0.
This is a loop that starts with a variable containing some value and then creates a string of character digits of ones and zeros.
The '0' + (x & 1) takes the character for a digit zero '0' and then adds to that character the value of the right most bit of x which have either a value of zero or of one. If the bit is zero then the result of the addition is '0' and if the bit is one then the result of the addition is '1'.
This character is then put into the buffer, the variable x is right shifted by one bit to move the next binary digit to the right most place.
The addition is then repeated.
The result is that you have a text string of zeros and ones as character digits.
Are you sure this is the correct source code? Looks to me like the text string result would need to be reversed in order to correctly represent the binary value.
buffer[index++] = '0'+ (x & 1);
This line progresses through what is presumably a char array, setting each character to the character '0' PLUS a value that will be equal to either 0 or 1. '0' + 0 is ''0'. '0' + 1 is '1'. The reason x & 1 will be either 0 or 1 is because this code is essentially checking if the low bit is on in x. The reason this works is because the line below then right shifts x by 1, then sets x equal to that value, which basically is knocking off the low bit, and shifting all other bits over by 1. In this way, x is traversed, and each bit is checked.
Please note, however. It appears that it will be written BACKWARDS!
In ASCII 0 has the ASCII value 48 and 1 has the ASCII value 49. IOW if you write putchar(48); you see a 0 on the screen
The buffer presumably being a char 2-dimensional array is assigned
either 48 or 49 because x & 1 evaluates to either 1 or 0.
so say you have a value x = 225 and want to convert it to readable text containing 0's and 1's
225 looks like this in binary
1110 0001
when you do 1110 0001 & 0x1 you mask out the last 1 left is 0000 0001
so adding 1 to 48 and converting the sum ito a character is 1
next the bits are shifted one step right x >>= 1
0111 0000
masking that with 0x1 is 0000 0000
so adding 0 to 48 and converting the sum to a character becomes 0
and so on until x is 0
I'm reading some source code for designing an Octree and found this in the code. I have removed some elements for simplication, but can anyone explain what i&4 is supposed to evaluate to?
for (int i = 0; i < 8; i++)
{
float j = i&4 ? .5f : -.5f;
}
& is the bitwise AND Operator.
It just does a bitwise operation of the value stored in i AND 0x4.
It exactly just isolates the third bit as 2^2 = 4.
Your expression in the loop checks if third bit is set in i and assigns to j (which must be a float!) 0.5 or if not set -0.5
I am not sure, but it may evaluate the bitwise and operation of i and 4 (100), so any number which has a '1' in its third bit will be evaluted to true, otherwise false.
Ex:
5 (101) & 4 (100) = 100 (4) which is different from 0 so its true
8 (1000) & 4 (100) = 0000 (0) which is false
The & operator in this case is a bitwise AND. Since the second operand is 4, a power of 2, it evaluates to 4 when i has its second least-significant bit set, and to 0 otherwise.
The for loop takes i from 0 to 7, inclusive. Consider bit representations of i in this range:
0000 - 0
0001 - 1
0010 - 2
0011 - 3
0100 - 4
0101 - 5
0110 - 6
0111 - 7
^
|
This bit determines the result of i & 4
Therefore, the end result of the conditional is as follows: if the second bit is set (i.e. when i is 4, 5, 6, or 7), the result is 0.5f; otherwise, it is -0.5f.
For the given range of values, this expression can be rewritten as
float j = (i >= 4) ? .5f : -.5f;
i & 4 just evaluate to true when the value-4 bit is set. In your case this only happens in the second half of the loop. So the code could actually be rewritten:
for (int i = 0; i < 4; i++)
{
float j = -.5f;
}
for (int i = 4; i < 8; i++)
{
float j = .5f;
}
Can anyone help what n&-n means??
And what is the significance of it.
It's an old trick that gives a number with a single bit in it, the bottom bit that was set in n. At least in two's complement arithmetic, which is just about universal these days.
The reason it works: the negative of a number is produced by inverting the number, then adding 1 (that's the definition of two's complement). When you add 1, every bit starting at the bottom that is set will overflow into the next higher bit; this stops once you reach a zero bit. Those overflowed bits will all be zero, and the bits above the last one affected will be the inverse of each other, so the only bit left is the one that stopped the cascade - the one that started as 1 and was inverted to 0.
P.S. If you're worried about running across one's complement arithmetic here's a version that works with both:
n & (~n + 1)
On pretty much every system that most people actually care about, it will give you the highest power of 2 that n is evenly divisible by.
I believe it is a trick to figure out if n is a power of 2. (n == (n & -n)) IFF n is a power of 2 (1,2,4,8).
N&(-N) will give you position of the first bit '1' in binary form of N.
For example:
N = 144 (0b10010000) => N&(-N) = 0b10000
N = 7 (0b00000111) => N&(-N) = 0b1
One application of this trick is to convert an integer to sum of power-of-2.
For example:
To convert 22 = 16 + 4 + 2 = 2^4 + 2^2 + 2^1
22&(-22) = 2, 22 - 2 = 20
20&(-20) = 4, 20 - 4 = 16
16&(-16) = 16, 16 - 16 = 0
It's just a bitwise-and of the number. Negative numbers are represented as two's complement.
So for instance, bitwise and of 7&(-7) is x00000111 & x11111001 = x00000001 = 1
I would add a self-explanatory example to the Mark Randsom's wonderful exposition.
010010000 | +144 ~
----------|-------
101101111 | -145 +
1 |
----------|-------
101110000 | -144
101110000 | -144 &
010010000 | +144
----------|-------
000010000 | 16`
Because x & -x = {0, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 32} for x from 0 to 32. It is used to jumpy in the for sequences for some applications. The applications can be to store accumulated records.
for(;x < N;x += x&-x) {
// do something here
++tr[x];
}
The loop traverses very fast because it looks for the next power of two to jump.
As #aestrivex has mentioned, it is a way of writing 1.Even i encountered this
for (int y = x; y > 0; y -= y & -y)
and it just means y=y-1 because
7&(-7) is x00000111 & x11111001 = x00000001 = 1