Question

I am working on a project where I need to deal at the byte level with integers. Since saving space is a primary consideration, I only need very small (and variable length ints).

Is there a way that I can turn the int '4096' into 3 bytes? or '1053' into a 2 bytes?

Obviously I cna do it manually = (byte[0] * 256) + (byte[1]), but i was wondering if there is an easier option to convert the int into x bytes and back again?

Was it helpful?

Solution

Can you? Sure. Will it save any space? Maybe, depending on how much work you want to do. You have to understand that the processor is 32-bit, meaning it has 4 byte registers, so that's how it's going to want to store and access things. To force a 3-byte "int" you'll have to keep it in a byte array, and extract it from the array to an aligned address before use. That means that if you store it short, the compiler will either pad it out (and you'll lose any efficiency you think you've created) or it will be a lot slower to read and write.

If this is a desktop app, how exactly is saving space a primary consideration, especially when talking 1 byte per element? The perf penalty for element access may change you mind about how critical that one byte is.

I'd argue that if that 1 byte truly is important, that maybe, just maybe, you're using the wrong language anyway. The number of bytes you'd save my not installing and using the CLR in the first place is a lot of those bytes.

Side note: You'd also do a shift, not a multiplication (though the compiler would likely get there for you).

OTHER TIPS

Just for added insanity, let's do it in C# using the old C-style union trick:

[StructLayout(LayoutKind.Explicit)]
struct OddUnion
{
    /* The 32-bit integer value */
    [FieldOffset(0)]
    public int IntegerValue;

    /* The bytes that overlap with it */
    [FieldOffset(0)]
    public byte Byte1;
    [FieldOffset(1)]
    public byte Byte2;
    [FieldOffset(2)]
    public byte Byte3;
    [FieldOffset(3)]
    public byte Byte4;
 }

And then, when you want to "convert", do this:

OddUnion myOddUnion;
myOddUnion.IntegerValue = 4096;
Byte secondByte = myOddUnion.Byte1;

But that really only helps if you're looking to "save" the cost of bit-shifting out a single byte from a word. I haven't looked at the generated SMIL, so I don't know whether this is any cheaper in comparison to any other solution.

You could do variable length integer encoding. The old method from years ago was to use the high bit of each byte to denote that the integer continues to another byte. So you lose one bit per byte, but gain small integers. This is mostly useful in persistent storage where every last byte counts.

Example: Assume we are dealing with unsigned integers, we would have

int  binary
0                       00000000
1                       00000001
...  
127                     01111111
128            00000001 10000000
129            00000001 10000001
...
255            00000001 11111111
256            00000010 10000000
...
16383          01111111 11111111
16384 00000001 10000000 10000000 

so 0-127 take 1 byte and 128-16383 takes 2 bytes, etc...

For more complex ways of doing this check out this page

BitConverter.GetBytes will get you the bytes.

and

BitConverter.ToInt32 will get you a 32 bit int from the bytes.

You have to do some bit shifting. It is much easir if you work with HEX, since every number(I mean every digit, but digit is for base 10, hexgit) represent four bits.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top