在C#中将Short[2]转换为Int32

8

我有一个在C#中的短数组,我需要将其中两个元素转换为Int32。我编写的代码如下:

uint pesoparz = (Convert.ToUInt16(values[0]));
Int32 pesotot = Convert.ToInt32(pesoparz *65536 + Convert.ToUInt16(values[1]));

其中values[]是短整型数组,pesotot是我想获得的Int32类型。代码可以运行,但当value[1] 超过 2^15时,会抛出系统溢出异常。

为什么会出现这个异常?


1
使用“取消选中”来解决这个问题。 - Bauss
@Bauss 对,这表面上修复了软件,但计算仍然不如预期。 - Codor
1
符号扩展可能会导致错误。尝试以下操作:uint pesoparz = ((values [1]&0xFFFF)<< 16)|(values [0]&0xFFFF); - jdweng
1
你可以始终使用 listByte.AddRange(BitConverter.GetBytes(shortArr[0])); listByte.AddRange(BitConverter.GetBytes(shortArr[1])); Int32 result = BitConverter.ToInt32(listByte.ToArray()); - mrogal.ski
@Bauss,我建议你把你的评论转换成答案。 - Codor
6个回答

5
您正在寻找unchecked,它可以关闭IntegerOverflow
  short left = -123;
  short right = -456;

  int result = unchecked(BitConverter.IsLittleEndian 
    ? (UInt16)left << 16 | (UInt16)right 
    : (UInt16)right << 16 | (UInt16)left);

你可以使用 BitConverter.IsLittleEndian 来检测将 short 合并成 int 的顺序。

5
您可以使用位运算符:
short[] parts = new short[2];
parts[0] = 1;
parts[1] = 2;

uint result = 0;

result = (ushort)parts[0] << 16 | (ushort)parts[1];

结果将以十六进制形式呈现为0x00010002或者以十进制形式呈现为65538

1
最好使用 shift 和 or 进行操作,并使用 unchecked 避免溢出错误:
int result = unchecked((int)(((uint)values[0] << 16) | values[1]));

0

试一下这个

uint pesoparz = (Convert.ToUInt16(values[0]));
Int32 pesotot = Convert.ToInt32(pesoparz *65536 + Convert.ToUInt32(values[1]));

看起来你已经达到了限制


0
short[] arr = new short[] { 512, -32767 };

int ival = ((int)arr[0] * 65536) + ((int)arr[1] & 0xffff);
// also:
// ival = ((int)arr[0] << 16) | ((int)arr[1] & 0xffff); 
Console.WriteLine(ival);

这将给出正确的结果33587201。 如果有诀窍,那就是使用强制转换将short转换为int,然后屏蔽掉不需要的部分(在本例中是符号扩展)。这既不需要Convert也不需要unchecked

0
你确定你的值数组中的每个值都适合 Int16 吗?
如果不是这样,即使您取消选择,结果也不是您想要的。首先,您需要决定如果 values[0] 或者 values1 大于 Int16 的限制该怎么办。
您的决定取决于这些值的含义。values[0] 是否代表您的结果Int32的最高 16 位,而values[1] 是最低 16 位?
在这种情况下,如果任一 values[0] 或 values1 超过 Int16.MaxValue,那么您应该抛出 ArgumentException。之后,您的代码就很简单了:
if (values[0] > Int16.MaxValue || values[1] > Int16.MaxValue)
    throw new ArgumentException("values should fit in two bytes");
Int32 result = values[0] << 0x10000 + values[1];
return result;

这也可能意味着允许两个值都大于0x10000,如果数字太大,您应该考虑自己想要什么结果。

顺便说一下,如果您的值分别表示Int32的一半,请考虑切换values[0]和values1的含义。几乎总是最不重要的位(LSB)在[0]中,而最重要的位(MSB)在1中。如果您遵循此约定,则无需编写这些转换器,可以使用BitConverter类

Int32 original = 0x12345678;
byte[] bytes = BitConverter.GetBytes(original);
foreach (var b in bytes)
    Console.WriteLine(b.ToString("02X"); // write in two digit hex format
// will write lines with 78 56 34 12
Int16[] Values = new Int16[]
{
    BitConverter.ToInt16(bytes),     // LSB
    BitConverter.ToInt16(bytes, 2),  // MSB
};
Int32 result = (Int32)values[0] + (Int32)values[1] << 0x10000;
Debug.Assert(original == result);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接