c#中是否有一个函数需要两个32位整数(int)并返回一个64位(长)?
听起来应该有一个简单的方法来做到这一点,但我找不到解决方案。
答案 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)
其中a
和b
是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。