I have the need to store a range of values (like 25-50 or 100-200), however to avoid a lot of database re-design and other work, I want to use a single Int32
to store both these numbers. I realize that I would only then have 16 bits for each number, but that's fine.
So, with two integer values this is pretty easy. I can do something like:
int mask = 50; //Right bits will have 50
mask |= (25 << 16); //Left bits will have 25
Console.WriteLine("Mask is: {0}", mask);
Console.WriteLine("Left is: {0}", (mask >> 16));
Console.WriteLine("Right is: {0}", (mask & 0xFFFF));
Now, I have the right 16 bits storing the value 50, and the left 16 bits storing the value 25.
So what's the question?
Now, I want to use the same technique but I want to store two non-integers. For example, 1.5 and 1.75, or 2.00 and 2.25. .NET doesn't seem to support bit shift operators on float
, single
, double
or decimal
. Plus, I need to also read these values eventually in Javascript so it's doubtful whatever bit encoding floating points use would be pletely patible between platforms.
What's the best way to do this? One approach I'm considering is just using integers, but dividing everything by 1000. That would give me 3 decimal point precision in both numbers, though I'd have to store the whole thing as a long
to store anything over 65. I'm not sure if this is the best approach though. Maybe there's something easy I'm missing.
I have the need to store a range of values (like 25-50 or 100-200), however to avoid a lot of database re-design and other work, I want to use a single Int32
to store both these numbers. I realize that I would only then have 16 bits for each number, but that's fine.
So, with two integer values this is pretty easy. I can do something like:
int mask = 50; //Right bits will have 50
mask |= (25 << 16); //Left bits will have 25
Console.WriteLine("Mask is: {0}", mask);
Console.WriteLine("Left is: {0}", (mask >> 16));
Console.WriteLine("Right is: {0}", (mask & 0xFFFF));
Now, I have the right 16 bits storing the value 50, and the left 16 bits storing the value 25.
So what's the question?
Now, I want to use the same technique but I want to store two non-integers. For example, 1.5 and 1.75, or 2.00 and 2.25. .NET doesn't seem to support bit shift operators on float
, single
, double
or decimal
. Plus, I need to also read these values eventually in Javascript so it's doubtful whatever bit encoding floating points use would be pletely patible between platforms.
What's the best way to do this? One approach I'm considering is just using integers, but dividing everything by 1000. That would give me 3 decimal point precision in both numbers, though I'd have to store the whole thing as a long
to store anything over 65. I'm not sure if this is the best approach though. Maybe there's something easy I'm missing.
- 7 The something easy you're missing might be changing your database schema. – James M Commented Jul 11, 2012 at 19:17
- 16 the best way is to go ahead and add the appropriate columns to the database. god help the next poor guy who has to deal with this hack. – Randy Commented Jul 11, 2012 at 19:17
- 7 I think that's what people call technical debt. And if you go with the hack instead of just correcting the design problem, you're just putting off the repayment of that debt (which is growing with pound interest all the while). Each hack is pounding the problem even more, so that eventually the only option is a plete rewrite, which will cost even more time/money. – Lèse majesté Commented Jul 11, 2012 at 19:26
- 1 @Lèsemajesté - In the end, your ment swayed me against this idea. I decided to stop trying to fit a round peg into a square hole, and instead just re-drill the hole to fit the peg correctly. It took about 2 days, but the design is now superior because of it. I think it's still a decent question though, as someone out there might have a legitimate reason to encode two floating points in a single int. – Mike Christensen Commented Jul 14, 2012 at 20:04
- 1 @Mike: It is a legitimate question. And I think even in cases where it's a hack, it might still be unavoidable (e.g. it took you 2 days to plete the redesign, but a non-negotiable deadline could have been 1 day away). That's why all software projects have technical debt, and not always due to inpetence. But it's just important to recognize that you are accruing a debt that grows the longer it's unpaid. Because it takes a very disciplined developer/team to actually schedule regularly allotted time to repay that technical debt after the deadline has been met. – Lèse majesté Commented Jul 14, 2012 at 20:46
5 Answers
Reset to default 7A little math could solve that.
First fix your precision, say 2 digits and your numbers range till 1000
both = Math.Round(num1, 2) * 10000 + Math.Round(num2, 2);
First 4 digits are for num1 and then you have num2.
You can get them back reversing the process.
As long as you do not have lots of decimal digits the easiest solution would be multiplying each number with whatever amount of decimals you want, then converting both numbers to ints, performing your bit operations and then storing the result in your database.
When reading them you simply split the number and then divide it by the factor you used before.
What you are asking is called in mathematics pairing function.
There are many pairing functions, amoung which there are Goedel's, Cantor's, etc.
Godel p.f. is not practical to encode nested languages, but it's excellent for plain languages with not so many symbols.
In C# you have BitConverter. You can convert the Float value from the DB to a byte array in code, then do whatever you need with it, then convert it back to Float before saving it to the DB.
See the post below for an example.
C#: Convert Byte array into a float
You can use the float to byte[] conversion from the answer to this question.
When you have a byte-array, you can use your masking technique.