我有一段简单的代码可以将Int转换为两个short
s:
public static short[] IntToTwoShorts(int a)
{
byte[] bytes = BitConverter.GetBytes(a);
return new short[] { BitConverter.ToInt16(bytes, 0), BitConverter.ToInt16(bytes, 2) };
}
如果我传入 1851628330 ( 0x6E5D 9B2A ),结果为:
{short[2]}
[0]: -25814
[1]: 28253
问题是 -25814 0xFFFF 9B2A
我尝试了各种风格,包括比特移位。发生了什么事?结果不是short
,并且没有 16 位!
答案 0 :(得分:1)
诀窍在于将两个ushort
合并到short
时使用int
:
public static short[] IntToTwoShorts(int a) {
unchecked {
return new short[] {
(short) a,
(short) (a >> 16)
};
}
}
public static int FromTwoShorts(short[] value) {
unchecked {
if (null == value)
throw new ArgumentNullException("value");
else if (value.Length == 1)
return (ushort)value[0]; // we don't want binary complement here
else if (value.Length != 2)
throw new ArgumentOutOfRangeException("value");
return (int)((value[1] << 16) | (ushort)value[0]); // ... and here
}
}
意外行为的原因是负数(如-25814
)表示为binary complements,因此您拥有相同的值(-25814
)在不同的整数类型中表示不同的:
-25814 == 0x9b2a // short, Int16
-25814 == 0xffff9b2a // int, Int32
-25814 == 0xffffffffffff9b2a // long, Int64
一些测试
int a = 1851628330;
short[] parts = IntToTwoShorts(a);
Console.WriteLine($"[{string.Join(", ", parts)}]");
Console.WriteLine($"{FromTwoShorts(parts)}");
Console.WriteLine($"{FromTwoShorts(new short[] { -25814 })}");
Console.WriteLine($"0x{FromTwoShorts(new short[] { -25814 }):X}");
结果:
[-25814, 28253]
1851628330
39722
0x9B2A
答案 1 :(得分:0)
我会用这样的方法解决问题:
public static short[] IntToTwoShorts(int a)
{
short retVar[2];
//Upper 16 byte masked with 0x0000FFFF
retVar[0] = (short) (a >> 16) & (65535);
//Lower 16 byte masked with 0x0000FFFF
retVar[1] = (short) (a >> 0) & (65535);
return retVar;
}
答案 2 :(得分:0)
问题不在于代码(尽管可能有更多efficient ways to do split integers)。通过尝试将int
表示为两个带符号的16位短路,您现在需要考虑符号位可能同时出现在shorts
中。因此评论ushort[]
将是两个16位值表示的更合适的选择。
问题似乎在于理解为什么4字节有符号整数(DWORD)无法在两个2字节有符号短路(WORD)中有效表示。
问题是-25814是0xFFFF 9B2A
事实并非如此 - 您已将-25814
表示为short
,因此它不可能是0xFFFF 9B2A
- 这是32位表示。它的16位表示只是9B2A
。
如果您在Windows上打开计算器,并将模式设置为程序员,并修改HEX
和DEC
基础,然后在DWORD
和{{1}之间翻转在表示值时,您应该看到从32位int中提取的16位值被正确表示(假设您理解了表示形式):
您原来的32位整数(DWORD)是1851628330:
高位字28253没有设置符号位,因此您似乎对转换为6E5D感到满意:
但是,如果低位字被解释为带符号短路,那么您会发现它的位符号已设置,因此它报告为负值。但是,表示(位和十六进制)确实正确表示原始32位int的最后16位。