将两个Int32组合到Int64中

时间:2012-04-01 17:40:53

标签: .net shift int64

拥有字典< Int64,byte>经常使用。我的意思是在大数据负载中运行数天的循环。 Int64来自两个Int32。该字节恰好是来自许多很长列表的那两个Int32之间的距离(计数)。

我在这个循环中需要做的是

  • 生成密钥
  • 如果词典中不存在键,则插入键和值
  • 如果密钥确实存在且新值(字节)小于现有值,则将现有值替换为新值

现在我正在使用直接数学来生成密钥,我知道有更快的方法,但我无法弄明白。我把shift作为一个标签,我认为这是如何优化它,但我无法弄明白。

然后当循环完成时,我需要从Int64中提取两个Int32以将数据插入到数据库中。

由于

每次评论我使用的数学将两个Int32组合成一个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());

最好的密钥可能不是Int64。我所拥有的是两个Int32,它们共同形成一个键。和一个字节的值。我需要快速查找该复合键。字典很快但它不支持复合键,因此我创建了一个实际上是复合键的单个键。在SQL Int32A中,Int32B形成PK。

我不使用复合键的原因是我希望Dictionary的查找速度和我的知识Dictionary不支持复合键。这是生产代码。在SQL表中实际上有第三个键(Int32 sID,Int32 IntA,Int32 IntB)。在这个解析器中,我一次只处理一个sID(并按顺序处理sID)。我开始使用SQL的复合键查找(运行中数十亿)。当我拉出IntA时,IntB输出到Dictionary以处理单个sID,然后在每个sID完成时加载到SQL我获得了100:1的性能提升。部分性能改进是插入,因为当我从字典插入时我可以按PK顺序插入。新的IntA和IntB不是按解析方式生成的,因此直接插入SQL会严重破坏索引,我需要在运行结束时重建索引。

3 个答案:

答案 0 :(得分:11)

如果要从Int32转换为Int64,可以使用具有显式布局的结构:

//using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct Int64ToInt32
{
    [FieldOffset(0)]
    public Int64 Int64Value;
    [FieldOffset(0)]
    public Int32 LeftInt32;
    [FieldOffset(4)]
    public Int32 RightInt32;
}

只需从字段中设置/获取值。

答案 1 :(得分:8)

听起来你只是想换班。我个人觉得在使用无符号类型而不是有符号类型时考虑位移是更简单的:

// 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;

反过来说:

ulong unsignedKey = (long) key;
uint lowBits = (uint) (unsignedKey & 0xffffffffUL);
uint highBits = (uint) (unsignedKey >> 32);
int i1 = (int) highBits;
int i2 = (int) lowBits;

完全有可能您不需要将所有这些转换都转换为无符号类型。这比我的理智更重要了:))

请注意,您需要将u1转换为ulong,以便移位在正确的空间中工作 - 将uint移位32位将无效。

请注意,这是 a 组合两个32位整数以获得64位整数的方法。无论如何,它不是唯一的方式。

(旁注:Bas的解决方案效果非常好 - 我对这种方法总是有点不舒服,没有特别的原因。)

答案 2 :(得分:1)

您可以使用位移来将两个32位值存储在一个64位变量中。

我将举一个小例子:

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

编辑:我看到我参加派对有点晚了,如果我没有犯错,只想查看VS:)