I'm working on a project where I need to pack numbers into a character array as tight as possible. By this, I mean that if there is a number that can be from 0 to say 30, it will take up only ln(30)/ln(2) bits and no more. I know it is possible to do, as I've done it before(unfortunately I've lost the source for it =-/), but I can't remeber the method I used. I could round the number of bits up to the nearest whole, but that is undesirable as it adds a lot of wasted space to the output that really doesn't need to be there.
The way I'm thinking of it right now is to keep 2 integers, the max value that can be represented (product of the max value of every number input so far) and the current value held. The value is calculated as N1 + M1*N2 + M1*M2*N3 etc where Nx is the Xth number inserted and Mx is the max value the the Xth number could be. When the stored max value is >= 256, it means there are at least 8 bits to be output, so the lower 8 bits are extracted from the stored value and both the value and max are divided 256. That doesn't seem like it would work though because the resulting max could then be a fraction and all of this should be done using integer math (at least thats how it seems to me since the stored number always has to be an integer and the output byte is an integer).
Write(N, M) = Insert N into the stream, Where N is a number from 0 to M
N = Read(M) = Extract a number from the stream, Where the number can be from from 0 to M
SN = Stored Number
SM = Stored Max
As an example:
SM = 1
SN = 0
Write(1, 10) makes SN = 1, SM = SM*10 = 10
Write(7, 10) makes SN = 1+7*SM = 71, SM = SM*10 = 100
Write(5, 10) makes SN = 71+5*SM = 571, SM = SM*10 = 1000
Read(10) returns (SN%10) = 1, and makes SN = SN/10 = 57
Read(10) returns (SN%10) = 7, and makes SN = SN/10 = 5
Read(10) returns (SN%10) = 5, and makes SN = SN/10 = 0
The problem occurs when the SM becomes >= the maximum value an unsigned integer (2^32-1) can hold, which is the reason I need to stream it. As you can see, there is no reguard for the bit boundaries and there really doesnt seem to be any need to care about them, but maybe that is the only way to stream them effectively. I chose to use byte stream because eventually it will get turned into that anyways. A solution that stores it in in an array of integers would work just as fine since I can easily convert it.
Does anybody know how to do this, or where I might at least find some hints? I've looked through all my backups for the past several years and I've done several web searches but I can't find any information on doing this.
The way I'm thinking of it right now is to keep 2 integers, the max value that can be represented (product of the max value of every number input so far) and the current value held. The value is calculated as N1 + M1*N2 + M1*M2*N3 etc where Nx is the Xth number inserted and Mx is the max value the the Xth number could be. When the stored max value is >= 256, it means there are at least 8 bits to be output, so the lower 8 bits are extracted from the stored value and both the value and max are divided 256. That doesn't seem like it would work though because the resulting max could then be a fraction and all of this should be done using integer math (at least thats how it seems to me since the stored number always has to be an integer and the output byte is an integer).
Write(N, M) = Insert N into the stream, Where N is a number from 0 to M
N = Read(M) = Extract a number from the stream, Where the number can be from from 0 to M
SN = Stored Number
SM = Stored Max
As an example:
SM = 1
SN = 0
Write(1, 10) makes SN = 1, SM = SM*10 = 10
Write(7, 10) makes SN = 1+7*SM = 71, SM = SM*10 = 100
Write(5, 10) makes SN = 71+5*SM = 571, SM = SM*10 = 1000
Read(10) returns (SN%10) = 1, and makes SN = SN/10 = 57
Read(10) returns (SN%10) = 7, and makes SN = SN/10 = 5
Read(10) returns (SN%10) = 5, and makes SN = SN/10 = 0
The problem occurs when the SM becomes >= the maximum value an unsigned integer (2^32-1) can hold, which is the reason I need to stream it. As you can see, there is no reguard for the bit boundaries and there really doesnt seem to be any need to care about them, but maybe that is the only way to stream them effectively. I chose to use byte stream because eventually it will get turned into that anyways. A solution that stores it in in an array of integers would work just as fine since I can easily convert it.
Does anybody know how to do this, or where I might at least find some hints? I've looked through all my backups for the past several years and I've done several web searches but I can't find any information on doing this.