有没有一种很好的方法将int分成两个短裤(.NET)?

Ign*_*cia 27 .net c# vb.net math

我认为这是不可能的,因为Int32有1位符号并且有31位数字信息,Int16有1位符号和15位数字信息,这导致有2位符号和30位信息.

如果这是真的那么我就不能有一Int32到两个Int16.这是真的?

提前致谢.

附加信息:使用Vb.Net,但我认为我可以毫无问题地翻译C#答案.

我最初想要做的是将一个转换UInt32为两个,UInt16因为这是一个与基于WORD的机器交互的库.然后我意识到这Uint不符合CLS,并试图用Int32和做同样的事情Int16.

EVEN WORSE:a = CType(c And &HFFFF, Int16);投掷OverflowException.我期望该语句与a = (Int16)(c & 0xffff);(不抛出异常)相同.

Jon*_*eet 36

这当然可以在不丢失信息的情况下完成.在这两种情况下,最终都会得到32位信息.它们是否用于符号位是无关紧要的:

int original = ...;

short firstHalf = (short) (original >> 16);
short secondHalf = (short) (original & 0xffff);

int reconstituted = (firstHalf << 16) | (secondHalf & 0xffff);
Run Code Online (Sandbox Code Playgroud)

在这里,reconstituted将始终相等original,因此不会丢失任何信息.

现在两条短路符号的含义是另一回事 - firstHalfiff original为负时secondHalf将为负,但如果设置了第15位(计数0-31),original则为负,这在原始形式中不是特别有意义.

  • 它在移位之前隐式地将其转换为int. (4认同)
  • @DrJokepu:你可以*假设移动和屏蔽将做什么,但是它存储在内存中.右移将进行符号扩展,但是对"短"的转换将有效地掩盖它. (2认同)

小智 13

这应该工作:

int original = ...;
byte[] bytes = BitConverter.GetBytes(original);
short firstHalf = BitConverter.ToInt16(bytes, 0);
short secondHalf = BitConverter.ToInt16(bytes, 2);
Run Code Online (Sandbox Code Playgroud)

编辑:

用0x7FFFFFFF测试,它的工作原理

byte[] recbytes = new byte[4];
recbytes[0] = BitConverter.GetBytes(firstHalf)[0];
recbytes[1] = BitConverter.GetBytes(firstHalf)[1];
recbytes[2] = BitConverter.GetBytes(secondHalf)[0];
recbytes[3] = BitConverter.GetBytes(secondHalf)[1];
int reconstituted = BitConverter.ToInt32(recbytes, 0);
Run Code Online (Sandbox Code Playgroud)


Rom*_*iko 7

Jon的答案,翻译成Visual Basic,没有溢出:

Module Module1
    Function MakeSigned(ByVal x As UInt16) As Int16
        Dim juniorBits As Int16 = CType(x And &H7FFF, Int16)
        If x > Int16.MaxValue Then
            Return juniorBits + Int16.MinValue
        End If
        Return juniorBits
    End Function

    Sub Main()
        Dim original As Int32 = &H7FFFFFFF    
        Dim firstHalfUnsigned As UInt16 = CType(original >> 16, UInt16)
        Dim secondHalfUnsigned As UInt16 = CType(original And &HFFFF, UInt16)
        Dim firstHalfSigned As Int16 = MakeSigned(firstHalfUnsigned)
        Dim secondHalfSigned As Int16 = MakeSigned(secondHalfUnsigned)

        Console.WriteLine(firstHalfUnsigned)
        Console.WriteLine(secondHalfUnsigned)
        Console.WriteLine(firstHalfSigned)
        Console.WriteLine(secondHalfSigned)
    End Sub
End Module
Run Code Online (Sandbox Code Playgroud)

结果:

32767
65535
32767
-1
Run Code Online (Sandbox Code Playgroud)

在.NET中CType(&Hffff, Int16)导致溢出,并(short)0xffff给出-1(没有溢出).这是因为默认情况下C#编译器使用未经检查的操作并检查VB.NET.

就个人而言,我喜欢Agg的答案,因为我的代码更复杂,并且Jon会在检查环境中导致溢出异常.

我还根据类代码创建了另一个答案,BitConverter针对此特定任务进行了优化.但是,它使用不安全的代码.

  • 如果你想在一般检查的环境中使用我的,你总是可以将它包装成"未选中":) (3认同)