.net 将两个Int32合并为一个Int64

.net 将两个Int32合并为一个Int64,.net,shift,int64,.net,Shift,Int64,有一本经常使用的字典。我的意思是在大数据负载中运行数天的循环中。Int64来自两个Int32。字节恰好是许多很长列表中两个Int32之间的距离(计数) 在这个循环中我需要做的是 生成密钥 如果字典中不存在键,则插入键和值 如果键不存在且新值(字节)小于现有值,则用新值替换现有值 现在我正在使用直接数学来生成关键点,我知道有更快的方法,但我无法理解。我把shift作为一个标签,因为我认为这是如何优化它的,但我无法理解它 然后,当循环完成时,我需要从Int64中提取两个Int32以将数据插入数据

有一本经常使用的字典。我的意思是在大数据负载中运行数天的循环中。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,它们一起构成一个键。和一个字节的值。我需要快速查找复合密钥。Dictionary很快,但它不支持复合键,所以我创建了一个实际上是复合键的键。在SQL Int32A中,Int32B构成PK


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

听起来你只是想要一个移位。我个人认为,在使用无符号类型而不是有符号类型时,考虑位移位更简单:

// 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;
您完全可能不需要将所有这些转换为无符号类型。这对我的理智来说比其他任何事情都重要:)

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

请注意,这是一种将两个32整数合并为64位整数的方法。无论如何,这不是唯一的办法


(旁注:Bas的解决方案工作得非常好-我只是对这种方法有点不舒服,没有具体原因。)

如果您想从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;
}

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

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

我将举一个小例子:

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
inta=10;
int b=5;
长c;
//将两个值打包到一个变量中
c=(长)a>32==a

c-((c>>32)你说的“直接数学”是什么意思?请展示一些代码来说明两个Int32和int64之间的关系。@OliCharlesworth我添加了一个简单的数学示例。
Int32。MaxValue
是2^32-1。你确定这就是你想要的吗?@OliCharlesworth请提出一种更好的方法来为字典生成一个键,其中该键实际上是一个复合键两个Int32的te。然后从该键中提取两个Int32。@BAM:my answer和Bas都以一种比您所拥有的更简单的方式组合了两个Int32值。我怀疑您的目标与我们所拥有的类似,但并没有完全实现。您是否反对仅使用两组32位完全正确Ogonaly?请注意,为了实现语言互操作性,.NET命名约定建议将
LeftInt32
RightInt32
Int64Value
、和
Int64ToInt32
作为名称。仅供参考,OP的更新问题包含的代码意味着它不仅仅是简单的比特咀嚼……哦!这很漂亮!它只会让me高兴。谢谢!这真是太好了,谢谢。一个问题:如果在构造函数中,我分配
LeftInt
righint
(来自构造函数参数)。有没有办法避免“字段(
LongValue
在这种情况下)必须在返回调用方之前完全分配”编译器错误消息?(除了将零指定给
LongValue
之外的其他方式)@tigrou我不认为有任何方法,但是如果在字段初始值设定项或构造函数中将LongValue设置为零,则不会对性能产生影响,因为这是结构的默认行为。仅供参考,OP的更新问题包含的代码暗示这不仅仅是简单的位咀嚼…@OliCharlesworth:我怀疑这是错误的更像是“这看起来可能有用”的产物而不是一个深思熟虑的决定。我添加了一条评论以进行检查。@OliCharlesworth我今天使用的是数学。我只是想让它更快。将查找从SQL移动到字典是一个很大的性能改进,并希望优化字典或是否有更好的方法。谢谢,在底部、顶部和中间进行了测试n、 请看我建议的化妆品编辑。@bum:是的,没关系-很抱歉弄错了方向:)
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