有没有一种很好的方法将int分成两个短裤(.NET)?
我认为这是不可能的,因为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);
(不会抛出exception)。
这应该工作:
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);
这当然可以在不丢失信息的情况下完成。 在这两种情况下,最终都会得到32位信息。 它们是否用于符号位是无关紧要的:
int original = ...; short firstHalf = (short) (original >> 16); short secondHalf = (short) (original & 0xffff); int reconstituted = (firstHalf << 16) | (secondHalf & 0xffff);
在这里, reconstituted
将始终等于original
,因此没有信息丢失。
现在两个短路的符号的含义是另一回事 - 如果original
是负的,则secondHalf
是负的,如果设置original
15位(计数0-31),则secondHalf
将是负的,这在原始forms。
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
结果:
32767 65535 32767 -1
在.NET中, CType(&Hffff, Int16)
导致溢出,而(short)0xffff
导致-1(没有溢出)。 这是因为默认情况下C#编译器使用未经检查的操作并检查VB.NET。
我个人喜欢Agg的答案 ,因为我的代码更复杂,而且Jon会在检查环境中导致溢出exception。
我还根据BitConverter
类的代码创建了另一个答案 ,针对此特定任务进行了优化。 但是,它使用不安全的代码。
是的,它可以使用掩蔽和位移来完成
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);
测试它并按预期打印-1。
EDIT2:改变了重建。 Int16到Int32的升级导致所有符号位扩展。 忘了,它必须是AND'ed。
为什么不? 为简单起见,让我们减少位数:假设我们有8位,其中左位是负位。
[1001 0110] // representing -22
您可以将其存储在2位4位中
[1001] [0110] // representing -1 and 6
我不明白为什么它不可能,你两次有8位信息
编辑:为了简单起见,我不仅减少了比特,还不使用2补码方法。 在我的例子中,左边的比特表示减号,其余部分被解释为正常的正二进制数
C#中的不安全代码,不会发生溢出,自动检测字节序:
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]) }; } } }
您可以在VB.NET中使用StructLayout:
校正:字是16bit,dword是32bit
_ Public Structure UDWord Public Value As UInt32 Public High As UInt16 Public Low As UInt16 Public Sub New(ByVal value As UInt32) Me.Value = value End Sub Public Sub New(ByVal high as UInt16, ByVal low as UInt16) Me.High = high Me.Low = low End Sub End Structure
签名将使用这些类型相同
_ Public Structure DWord Public Value As Int32 Public High As Int16 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
编辑:
我有点匆匆几次发布/编辑我的anwser,然后解释这个解决方案,所以我觉得我还没有完成我的答案。 所以我现在要这样做:
将StructLayout显式化为结构需要您使用FieldOffset属性[FieldOffsetAttribute]提供每个字段的定位(按字节偏移量) [StructLayoutAttribute ]
使用这两个属性,您可以创建重叠字段,即联合 。
第一个字段(DWord.Value)是32位整数,偏移量为0(零)。 要分割这个32位整数,你将有两个额外的字段再次从0(零)的偏移开始,然后第二个字段2更多的字节关闭,因为16位(短)整数是2字节a-peice。
从我记得的情况来看,通常当你分裂一个整数时,他们通常将前半部分称为“高”,然后将下半部分称为“低”; 从而命名我的另外两个领域。
通过使用这样的结构,您可以为运算符创建重载并输入widing / narrowing,以便从Int32类型轻松交换到此DWord结构,以及在VB.NET中运算符重载
您可以使用StructLayout执行此操作:
[StructLayout(LayoutKind.Explicit)] struct Helper { [FieldOffset(0)] public int Value; [FieldOffset(0)] public short Low; [FieldOffset(2)] public short High; }
使用它,您可以获得完整的值作为int,而低的部分,高的部分作为短。
就像是:
var helper = new Helper {value = 12345};
由于存储宽度(32位和16位),如果Int32大于32767,将Int32转换为Int16可能意味着丢失信息。
如果你看一下比特表示,那你就是对的。
你可以使用无符号整数执行此操作,因为它们没有符号位。
如果您正在使用c ++,您可能也对StructLayout或联合感兴趣。
Int32 num = 70000;
上述就是C#学习教程:有没有一种很好的方法将int分成两个短裤(.NET)?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
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 }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1004872.html