Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有一种很好的方法可以将一个int拆分为两个短裤(.NET)?_C#_.net_Vb.net_Math - Fatal编程技术网

C# 有没有一种很好的方法可以将一个int拆分为两个短裤(.NET)?

C# 有没有一种很好的方法可以将一个int拆分为两个短裤(.NET)?,c#,.net,vb.net,math,C#,.net,Vb.net,Math,我认为这是不可能的,因为Int32具有1位符号和31位数字信息,而Int16具有1位符号和15位数字信息,这导致具有2位符号和30位信息 如果这是真的,那么我不能让一个Int32变成两个Int16。这是真的吗 提前谢谢 额外信息:使用Vb.Net,但我认为我可以毫无问题地翻译C#答案 最初我想做的是将一个UInt32转换为两个UInt16,因为这是一个与基于单词的机器交互的库。然后我意识到Uint不符合CLS,并尝试对Int32和Int16执行同样的操作 更糟糕的是:做a=CType(c和&HF

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

如果这是真的,那么我不能让一个
Int32
变成两个
Int16
。这是真的吗

提前谢谢

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

最初我想做的是将一个
UInt32
转换为两个
UInt16
,因为这是一个与基于单词的机器交互的库。然后我意识到
Uint
不符合CLS,并尝试对
Int32
Int16
执行同样的操作


更糟糕的是:做
a=CType(c和&HFFFF,Int16)抛出溢出异常
。我希望该语句与
a=(Int16)(c&0xffff)相同(不会引发异常)。

由于存储宽度(32位和16位),如果您的Int32大于32767,则将Int32转换为Int16可能意味着信息丢失。

是的,可以使用掩蔽和位移位来完成

 Int16 a,b;
 Int32 c;

 a = (Int16) (c&0xffff);
 b = (Int16) ((c>>16)&0xffff);
编辑

回答这个评论。重建工程良好:

 Int16 a, b;
 Int32 c = -1;

 a = (Int16)(c & 0xffff);
 b = (Int16)((c >> 16) & 0xffff);

 Int32 reconst = (((Int32)a)&0xffff) | ((Int32)b << 16);

 Console.WriteLine("reconst = " + reconst);
int16a,b;
Int32 c=-1;
a=(Int16)(c&0xffff);
b=(Int16)((c>>16)和0xffff);

Int32重建=((Int32)a)和0xffff)|((Int32)b如果您查看位表示,那么您是正确的


不过,您可以对无符号整数执行此操作,因为它们没有符号位。

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

int original = ...;

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

int reconstituted = (firstHalf << 16) | (secondHalf & 0xffff);
int-original=。。。;
短上半段=(短)(原始>>16);
短后半部分=(短)(原始和0xffff);

int restructured=(firstHalf为什么不呢?为了简单起见,让我们减少位的数量:假设我们有8位,其中左位是负位

[1001 0110] // representing -22
您可以将其存储为2乘以4位

[1001] [0110] // representing   -1 and 6
我不明白为什么不可能,你有两次8位信息


编辑:为了简单起见,我不仅减少了位,而且也不使用2互补方法。在我的例子中,左边的位表示减数,剩下的被解释为正的正数二进制数

如果使用C++,你可能对结构布局或联合感兴趣。
int original = ...;
byte[] bytes = BitConverter.GetBytes(original);
short firstHalf = BitConverter.ToInt16(bytes, 0);
short secondHalf = BitConverter.ToInt16(bytes, 2);
编辑:

通过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);
,已翻译为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
结果:

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

就我个人而言,我喜欢,因为我的代码更复杂,而Jon的代码会在checked环境中导致溢出异常


我还基于BitConverter类的代码对此特定任务进行了优化。但是,它使用了不安全的代码。

您可以在VB.NET中使用StructLayout:

更正:字是16位,dword是32位

_
公共结构UDWord
作为UInt32的公共价值
公共高等教育学院(UInt16)
公共低至UInt16
公共子新建(ByVal值为UInt32)
价值=价值
端接头
公共子新建(ByVal高达UInt16,ByVal低达UInt16)
我高
Me.Low=低
端接头
端部结构
只需使用这些类型就可以了

<StructLayout(LayoutKind.Explicit, Size:=4)> _
   Public Structure DWord
      <FieldOffset(0)> Public Value As Int32
      <FieldOffset(0)> Public High As Int16
      <FieldOffset(2)> Public Low As Int16

      Public Sub New(ByVal value As Int32)
         Me.Value = value
      End Sub

      Public Sub New(ByVal high as Int16, ByVal low as Int16)
         Me.High = high
         Me.Low = low
      End Sub
   End Structure
_
公共结构德沃德
Int32的公共价值
公营高达国际16
公众低至国际16
Public Sub New(ByVal值为Int32)
价值=价值
端接头
新公共子系统(ByVal高达Int16,ByVal低达Int16)
我高
Me.Low=低
端接头
端部结构
编辑:

我发布/编辑我的anwser的几次都有点匆忙,还没有解释这个解决方案,所以我觉得我还没有完成我的答案。所以我现在就要这么做:

将StructLayout显式用于结构需要使用FieldOffset属性提供每个字段的位置(按字节偏移)

使用这两个属性可以创建重叠字段,即

第一个字段(DWord.Value)将是偏移量为0(零)的32位整数。若要拆分此32位整数,您将有两个额外的字段,从偏移量为0(零)开始,然后第二个字段再减去2个字节,因为16位(短)整数是2个字节a-peice

据我回忆,通常当你拆分一个整数时,他们通常会将前半部分称为“高”,然后将后半部分称为“低”;这样,我的另外两个字段就被命名为“低”

通过使用这样的结构,您可以为运算符创建重载,并键入widing/Nerrowing,以便轻松地从例如Int32类型交换到此DWord结构,以及比较

C#中的不安全代码,不会发生溢出,自动检测endianness:

using System;
class Program
{
    static void Main(String[] args)
    {
        checked // Yes, it works without overflow!
        {
            Int32 original = Int32.MaxValue;
            Int16[] result = GetShorts(original);
            Console.WriteLine("Original int: {0:x}", original);
            Console.WriteLine("Senior Int16: {0:x}", result[1]);
            Console.WriteLine("Junior Int16: {0:x}", result[0]);
            Console.ReadKey();
        }
    }
    static unsafe Int16[] GetShorts(Int32 value)
    {
        byte[] buffer = new byte[4];
        fixed (byte* numRef = buffer)
        {
            *((Int32*)numRef) = value;
            if (BitConverter.IsLittleEndian)
                return new Int16[] { *((Int16*)numRef), *((Int16*)numRef + 1) };
            return new Int16[] { 
                (Int16)((numRef[0] << 8) | numRef[1]),  
                (Int16)((numRef[2] << 8) | numRef[3])
            };
        }
    }
}
使用系统;
班级计划
{
静态void Main(字符串[]参数)
{
选中//是,它工作时不会溢出!
{
Int32原始值=Int32.MaxValue;
Int16[]结果=GetShorts(原始);
WriteLine(“原始int:{0:x}”,原始);
WriteLine(“高级Int16:{0:x}”,结果[1]);
WriteLine(“Junior Int16:{0:x}”,结果[0]);
Console.ReadKey();
}
}
静态不安全Int16[]GetShorts(Int32值)
{
字节[]缓冲区=新字节[4];
固定(字节*numRef=缓冲区)
{
*((Int32*)numRef)=值;
if(位转换器.IsLittleEndian)
返回新的Int16[]{*((Int16*)numRef),*((Int16*)numRef+1)};
using System;
class Program
{
    static void Main(String[] args)
    {
        checked // Yes, it works without overflow!
        {
            Int32 original = Int32.MaxValue;
            Int16[] result = GetShorts(original);
            Console.WriteLine("Original int: {0:x}", original);
            Console.WriteLine("Senior Int16: {0:x}", result[1]);
            Console.WriteLine("Junior Int16: {0:x}", result[0]);
            Console.ReadKey();
        }
    }
    static unsafe Int16[] GetShorts(Int32 value)
    {
        byte[] buffer = new byte[4];
        fixed (byte* numRef = buffer)
        {
            *((Int32*)numRef) = value;
            if (BitConverter.IsLittleEndian)
                return new Int16[] { *((Int16*)numRef), *((Int16*)numRef + 1) };
            return new Int16[] { 
                (Int16)((numRef[0] << 8) | numRef[1]),  
                (Int16)((numRef[2] << 8) | numRef[3])
            };
        }
    }
}
[StructLayout(LayoutKind.Explicit)]
        struct Helper
        {
            [FieldOffset(0)]
            public int Value;
            [FieldOffset(0)]
            public short Low;
            [FieldOffset(2)]
            public short High;
        }
var helper = new Helper {value = 12345};
        string str = Convert.ToString(num, 2);
    //convert INT32 to Binary string   
        Int32 strl = str.Length;
    //detect string length


        string strhi, strlo;
    //ifvalue is greater than 16 bit 
        if (strl > 16)
        {
           int lg = strl - 16;
          //dtect bits in higher word 
           strlo = str.Substring(lg, 16);
     ///move lower word string to strlo 

            strhi = str.Substring(0, lg);
   //mov higher word string to strhi

        }
        else
//if value is less than 16 bit
        {
           strhi = "0";
//set higher word zero
           strlo = str;
///move lower word string to strlo 

        }

        Int16 lowword, hiword;
        lowword = Convert.ToInt16(strlo, 2);
        hiword = Convert.ToInt16(strhi, 2);
        ////convert binary string to int16
        }
public (ushort, ushort) SplitToUnsignedShorts(uint value)
{
    ushort v1 = (ushort) (value / 0x10000);
    ushort v2 = (ushort) (value % 0x10000);

    return (v1, v2);
}
public (ushort, ushort) SplitToUShorts(uint value)
    => ((ushort)(value / 0x10000), (ushort)(value % 0x10000));