Combining two Int32 Into Int64
Have a dictionary <Int64, byte> which is often used. I mean a loop that runs for days on a large data load. Int64 comess from two Int32. A byte is the distance (count) between these two Int32s from many very long lists.
What I need to do in this loop:
- Generate key
- If there is no key in the dictionary, enter the key and value
- If the key exists and the new value (byte) is less than the existing value, replace the existing value with the new value
Right now I am using direct math to generate the key and I know there is a faster way, but I cannot figure it out. I put shift as a tag as I think this is how to optimize it but I can't figure it out.
Then, when the loop is complete, I need to extract two Int32s from Int64 to insert data into the database.
thank
For a comment on the math I am using to concatenate two Int32s into one Int64
Int64 BigInt;
Debug.WriteLine(Int32.MaxValue);
Int32 IntA = 0;
Int32 IntB = 1;
BigInt = ((Int64)IntA * Int32.MaxValue) + IntB;
Debug.WriteLine(BigInt.ToString());
IntA = 1;
IntB = 0;
BigInt = ((Int64)IntA * Int32.MaxValue) + IntB;
Debug.WriteLine(BigInt.ToString());
IntA = 1;
IntB = 1;
BigInt = ((Int64)IntA * Int32.MaxValue) + IntB;
Debug.WriteLine(BigInt.ToString());
And the best key might not be Int64. I have two Int32s that together form a key. And the value of the byte. I need a quick lookup for this compound key. The dictionary is fast, but it doesn't support composite key, so I create one key, which is actually composite. In SQL, Int32A, Int32B form PK.
The reason I don't use a composite key is because the dictionary lookup speed is fast and to my knowledge the dictionary does not support composite key. This is production code. There is actually a third key in the SQL table (Int32 sID, Int32 IntA, Int32 IntB). In this parser, I only deal with one SID at a time (and sIDs are processed in order). I started with a tricky search for the SQL keyword (billions in run). When I pulled IntA, IntB into a dictionary to handle one sID, then loaded into SQL at the end of each sID, I got a performance improvement of 100: 1. Part of the performance improvement is inserted the same as when inserting from a Dictionary which I can insert in PK order ... New IntA and IntB are not created, sorted by parse, so direct insertion in SQL will severely fragment the index.and I will need to rebuild the index at the end of the run.
source to share
It looks like you just want a shift. Personally, I find it easier to think about bitmotion when using unsigned types instead of signed ones:
// Note: if you're in a checked context by default, you'll want to make this
// explicitly unchecked
uint u1 = (uint) int1;
uint u2 = (uint) int2;
ulong unsignedKey = (((ulong) u1) << 32) | u2;
long key = (long) unsignedKey;
And vice versa:
ulong unsignedKey = (long) key;
uint lowBits = (uint) (unsignedKey & 0xffffffffUL);
uint highBits = (uint) (unsignedKey >> 32);
int i1 = (int) highBits;
int i2 = (int) lowBits;
It is quite possible that you do not need all these conversions for unsigned types. This is more for my sanity than anything else :)
Note that you need to cast u1
in ulong
, so the job of shifting in the right space - shifting a uint
by 32 bits will do nothing.
Note that this is a way of combining two 32-bit integers to get a 64-bit integer. This is not the only way in any way.
(Side note: Bas's solution works great - I'm just always a little uncomfortable with this approach, for no particular reason.)
source to share
If you want to convert back and forth from Int32 to Int64, you can use an explicit layout structure:
//using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct Int64ToInt32
{
[FieldOffset(0)]
public Int64 Int64Value;
[FieldOffset(0)]
public Int32 LeftInt32;
[FieldOffset(4)]
public Int32 RightInt32;
}
Just set / get values ββfrom fields.
source to share
You can use bit offset to store two 32-bit values ββin one 64-bit variable.
I'll give you a small example:
int a = 10;
int b = 5;
long c;
//To pack the two values in one variable
c = (long)a << 32;
c = c + (long)b;
//the 32 most significant bits now contain a, the 32 least significant bits contain b
//To retrieve the two values:
c >> 32 == a
c - ((c>>32)<<32) == b
Edit: I see that I am a little late to the party, just want to check out VS if I am not wrong :)
source to share