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.

+3


source to share


3 answers


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.)

+7


source


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.

+11


source


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 :)

+1


source







All Articles