I have three integers {a
, b
, c
} that range (say) between the following values:
a
- {1 to 120, in jumps of 1}
b
- {-100 to 100, in jumps of 5}
c
- {1 to 10, in jumps of 1}
Due to space considerations, I would like to represent these three values using 1-byte ONLY, meaning, a single integer (in the range of -127..128) will represent the results of {a
, b
, c
} and be stored in a binary format to disk.
Later, when I read the binary data, I will know how to 'parse' this 1-byte to get the values of {a
, b
, c
}.
Any idea how to achieve that? (note: if need be, in order to support this design, I can 'compromise' on the ranges; for example, say, a
can be in jumps of 5. b
can also be in jumps of 10 etc)
Just from a numbers point of view we have:
a = 120 values, b = 41 values, c = 10 values
That makes for a total of 49,200 unique values. A byte can only represent 256 values, so you'd need to use at least 16-bits (two bytes) to represent your range.
One way to do so would be through bit shifting.
As an example, you can store four 8-bit values in a 32-bit value, and extract them like so:
#include <iostream>
using namespace std;
int pack32(char *v)
{
return (v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3];
}
void unpack32(int a, char *v)
{
v[0] = a >> 24;
v[1] = a >> 16;
v[2] = a >> 8;
v[3] = a;
}
int main()
{
char v[4] = {32, 64, 16, 8};
cout << "Original values: ";
for (int i = 0; i < 4 ; i++)
cout << (int)v[i] << " ";
cout << endl;
int q = pack32(v);
cout << "Packed: " << q << endl;
unpack32(q, v);
cout << "Unpacked: ";
for (int i = 0; i < 4; i++)
cout << (int)v[i] << " ";
return 0;
}
Code relevant to your needs:
unsigned short pack32(unsigned a, char b, unsigned c)
{
// Layout:
// Bits 0 - 5 are reserved for a
// Bits 6 - 12 are reserved for b
// Bits 13 - 15 are reserved for c
// Assumptions:
// a is [2, 120] in steps of 2
// b is [-100, 100] in steps of 5
// c is [1, 10] in steps of 1
// Shift a from [2, 120] to [0, 59]
unsigned a2 = (a - 2) >> 1;
// Shift b from [-100, 100] to [0, 40]
unsigned b2 = b / 5 + 20;
// Shift c from [1, 10] to [0, 9]
unsigned c2 = c - 1;
return a2 + (b2 << 5) + (c2 << 12);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With