C# - 从两个Int32中创建一个Int64

时间:2009-05-05 22:45:39

标签: c#

c#中是否有一个函数需要两个32位整数(int)并返回一个64位(长)?

听起来应该有一个简单的方法来做到这一点,但我找不到解决方案。

7 个答案:

答案 0 :(得分:19)

尝试以下

public long MakeLong(int left, int right) {
  //implicit conversion of left to a long
  long res = left;

  //shift the bits creating an empty space on the right
  // ex: 0x0000CFFF becomes 0xCFFF0000
  res = (res << 32);

  //combine the bits on the right with the previous value
  // ex: 0xCFFF0000 | 0x0000ABCD becomes 0xCFFFABCD
  res = res | (long)(uint)right; //uint first to prevent loss of signed bit

  //return the combined result
  return res;
}

答案 1 :(得分:9)

为了清楚起见......虽然接受的答案确实可以正常工作。所有呈现的衬垫似乎都不会产生准确的结果。

这是一个可以正常工作的单线程

long correct = (long)left << 32 | (long)(uint)right;

以下是一些代码,您可以自行测试:

long original = 1979205471486323557L;
int left = (int)(original >> 32);
int right = (int)(original & 0xffffffffL);

long correct = (long)left << 32 | (long)(uint)right;

long incorrect1 = (long)(((long)left << 32) | (long)right);
long incorrect2 = ((Int64)left << 32 | right);
long incorrect3 = (long)(left * uint.MaxValue) + right;
long incorrect4 = (long)(left * 0x100000000) + right;

Console.WriteLine(original == correct);
Console.WriteLine(original == incorrect1);
Console.WriteLine(original == incorrect2);
Console.WriteLine(original == incorrect3);
Console.WriteLine(original == incorrect4);

答案 2 :(得分:4)

尝试

(long)(((long)i1 << 32) | (long)i2)

这会将第一个int向左移动32位(int的长度),然后在第二个int中移动ors,所以最终将两个整数连接在一起。

答案 3 :(得分:2)

这应该可以解决问题

((Int64) a << 32 | b)

其中ab是Int32。虽然您可能想要检查最高位会发生什么。或者只是将其放在“unchecked {...}”块中。

答案 4 :(得分:1)

要小心这一点,但是因为你会在小端/大端机器上遇到问题(exp Mono平台并不总是小端)。另外,你必须处理扩展标志。数学上以下是相同的,但处理符号扩展并且与平台无关。

return (long)( high * uint.MaxValue ) + low;

在运行时进行jitted时,它会产生类似于twiddling的性能。这是解释语言的好处之一。

答案 5 :(得分:1)

请小心符号位。这是一个快速的ulong解决方案,它从小字节序到大字节序也不可移植:

    var a = 123;
    var b = -123;

    unsafe
    {
        ulong result = *(uint*)&a;

        result <<= 32;
        result |= *(uint*)&b;
    }

答案 6 :(得分:0)

当i2 <0时将出现问题-将设置高32位(0xFFFFFFFF,1xxx ...二进制)-Thecoop错误
更好的是(Int64)((((UInt64)i1 << 32)|(UInt32)i2)

或者只是C ++方式

public static unsafe UInt64 MakeLong(UInt32 low, UInt32 high)
{
    UInt64 retVal;
    UInt32* ptr = (UInt32*)&retVal;
    *ptr++ = low;
    *ptr = high;
    return retVal;
}

UInt64 retVal;
unsafe
{
    UInt32* ptr = (UInt32*)&retVal;
    *ptr++ = low;
    *ptr = high;
}

但最好的解决方案是这里;-)
[StructLayout(LayoutKind.Explicit)]
[FieldOffset()]
https://stackoverflow.com/questions/12898591
(甚至不安全) 无论如何,FieldOffset都适用于每个项目,因此您必须指定每个一半的位置,并记住负号是零补码,因此例如。低<0和高> 0毫无意义-例如-1,0可能会将Int64表示为4294967295。