Packets coming over a network have padding bytes added at the end for alignment. I want to skip these bytes but the packet size is variable but known. Given a number n, how do I round it up to the next 4-byte alignment?
For any integer n and any stride k (both positive), you can compute the smallest multiple of k that's not smaller than n via:
(n + k - 1) / k * k
This uses the fact that integral division truncates.
Another version. n is the number you want to alight to 4 (say k). Formula would be=n+k-n%k (where % is modulus)
For example (in Unix bc calculator)
k=4
n=551
n+k-n%k
552
to check that it is aligned:
scale=4
552/4
138.0000
Related
I am trying to understand what is happening in this bitwise operation that is used to set the size of a char array but I do not fully understand it.
unsigned long maxParams = 2;// or some other value, I just chose 2 arbitrarily
unsigned char m_uParamBitArray[(((maxParams) + ((8)-1)) & ~((8)-1))/8];
What size is this array set to based on the value of maxParams?
This counts the number of 8-bit chars needed to fit maxParams bits.
+7 is to round up to the next multiple of 8.
0 -> 7 will round to 0 char
1 -> 8 will round to 1 char
After division by 8. Which is done by /8
The bitwise and is to discard the last three bits before dividing by 8.
When maxParams is not divisible by eight, the first part of the formula formula rounds it up to the next multiple of eight; otherwise, it leaves the number unchanged. The second part of the formula divides the result by eight, which it can always do without getting a remainder.
In general, if you want to round up to N without going over it, you can add N-1 before the division:
(x + (N - 1)) / N
You can safely drop the & ~((8)-1) part of the expression:
(maxParams + (8-1))/8
I have a file which is nothing but an array of longs (8-byte integers).
I know that each consecutive long is larger in value than its predecessor.
What simple and complicated ways are there to compress this data?
What I have thought of:
Assessing the largest difference and storing only the difference between the longs, assuming it takes fewer bits per long to represent the difference.
Any suggestions are welcome.
Overall, your idea seems correct.
Let's say you have L0 .. L1 ... Ln-1 .. Ln your n unsigned longs, such as
Lk+1 >= Lk, and obviously by definition L0 >= 0 and Lk <= Lmax.
Let's call diffk = Lk+1 - Lk the difference function which represents the data you plan on compressing.
If we study the sum of diff0 .. diff1 ... diffn-2 .. diffn-1 :
diff0 + diff1 + .. + diffn-2 + diffn-1 = L1 - L0 + L2 - L1 + .. + Ln-1 - Ln-2 + Ln - Ln-1,
This simplifies to Ln - L0 : the sum of all differences is equal to Ln - L0.
So on average the function diffn has a value of (Ln - L0) / (n - 1), whereas Lk has an average value of (Ln - L0) / 2.
As n >> 2, we can therefore say that average(diffn) << average(Ln), which means you will need less bits to compress the diffn information.
As of how to do such a compression, without more information on the data distribution it's difficult to assess what the best possible algorithm could be.
You can start with a trivial scheme like this :
if(diffk < 128) return a byte with the first bit set, and the 7 remaining bits containing the value of diffk
else if(diffk < 16384) return a byte with the first bit unset, and the 7 remaining bits containing the first 7 bits of the value of diffk, then another byte with the first bit set and the 7 bits remaining containing the rest of the value of diffk, etc...
To decompress it's very easy, you read a byte, if the first bit is set, you know you only need to read the next 7 bits, if not, you read and store 7 bits and you go on to the next byte, etc.
I'm looking for a way (preferably recursive) to add two integers with their msb aligned.
For example: 125 + 25 = 375.
I tried to reverse the digits to effectively align them but the carrying would be all wrong. ie. 526 (625) + 05 (50) = 531.
1) Calculate number of digits of both numbers using a while / 10 loop
2) Get the difference
3) Multiply smallest number by 10 ^ difference
4) Add them together
you will need to include math.h for this. Assuming m and n are natural numbers, the below works by multiplying the smaller number by 10 (if needed) until it has the same number of digits as the larger, then adding.
int funkyAdd (int m, int n)
{
if ((m<=0)||(n<=0)){return -1;}
int smaller=std::min(m,n);
int larger=std::max(m,n);
while (floor(log10(smaller))<floor(log10(larger))){smaller*=10;};
return (smaller+larger);
}
If I impement BigInteger with a character array (in C++), in terms of power of 10, what is my upper bound in a 32bit system?
In other words,
- 10^x < N <= 10^x
(first character is reserved for sign).
What is x in 32 bit system?
Please ignore for now that we have reserved memory for OS and consider all 4GB memory is addressable by us.
An 8-bit byte can hold 28, or 256 unique values.
4GB of memory is 232, or 4294967296 bytes.
Or 4294967295, if we subtract the one byte that you want to reserve for a sign
That's 34359738360 bits.
This many bits can hold 234359738360 unique values.
- 10^x < N <= 10^x
(first character is reserved for sign).
What is x in 32 bit system?
Wolfram Alpha suggests - 10^1292913986 < N <= 10^1292913986 as the largest representable powers of 10.
So x is 1,292,913,986.
(−(2^(n−1))) to (2^(n−1) − 1) calculates the range of a signed integer where n is the number of bits.[1]
Assuming your referring to the whole 4GB of memory being allocated, that is 232 (4,294,967,295) addressable bytes in 32 bit memory space, which is 235 (34,359,738,368) bits.
Put that into the formula at the start and you get a range of - (2235-1) to 2235-1 -1
This is assuming you use a bit for a sign, instead of a whole byte. If your going a use a whole byte for sign, you should calculate the unsigned range of 235-8 bits. Which is from 0 to 2235-8−1
According to this page, to convert from an exponent of base 2 to an exponent of base 10, you should use the formula x = m*ln(2)/ln(10),where you are converting from 2m to 10 x.
Therefore, your answer is that the upper bound is 10235-8*ln(2)/ln(10). I'm not going to even attempt to change that exponent into a decimal value.
Looking for a better algorithmic approach to my problem. Any insights to this is greatly appreciated.
I have an array of numbers, say
short arr[] = [16, 24, 24, 29];
// the binary representation of this would be [10000, 11000, 11000, 11101]
I need to add the bit in position 0 of every number and bit in position 1 of every number and so on.. store it in an array, so my output array should look like this:
short addedBitPositions = [4, 3, 1, 0, 1];
// 4 1s in leftmost position, 3 1s in letmost-1 position ... etc.
The solution that I can think is this:
addedBitPosition[0] = (2 pow 4) & arr[0] + (2 pow 4) & arr[1] +
(2 pow 4) & arr[2] + (2 pow 4) & arr[3];
addedBitPosition[1] = (2 pow 3) & arr[0] + (2 pow 3) & arr[1] +
(2 pow 3) & arr[2] + (2 pow 3) & arr[3];
... so on
If the length of arr[] grows to M and the number of bits in each M[i] grows to N, then the time complexity of this solution is O(M*N).
Can I do better? Thanks!
You may try masking each number with masks 0b100...100...100...1 with 1's in each k positions. Then add the masked numbers together — you will receive sums of bits in positions 0, k, 2k... Repeat this with mask shifted left by 1, 2, ..., (k-1) to receive the sums for other bits. Of course, some more bithackery is needed to extract the sums. Also, k must be chosen such that 2 ** k < M (the length of the array), to avoid overflow.
I'm not sure it is really worth it, but might be for very long arrays and N > log₂ M.
EDIT
Actually, N > log₂ M is not a strict requirement. You may do this for "small enough" chunks of the whole array, then add together extracted values (this is O(M)). In bit-hacking the actual big-O is often overshadowed by the constant factor, so you'd need to experiment to pick the best k and the size of array chunk (assuming this technique gives any improvement over the straightforward summation you described, of course).