在.NET中将单个转换为两个UInt16值

时间:2010-04-30 18:12:51

标签: c# .net c

在C的好时光中,我可以将一个浮点数转换为int(假设一个32位系统),做一些位操作(按位和右移等),并得到上下16浮点数的十六进制位表示,然后我可以存储在两个短值中。我没有在C#中看到一种简单的方法。

System.Convert.ToUInt16只是执行浮点转换为int转换(即使我向右移动),如果浮点数小于0,则保留值0,这不是所需的效果。

//Useless leaves me with a value of 0
UIN16 s1 = (UInt16)((System.Convert.ToUInt32(d2) & 0xffff0000) >> 16);   //Capture the high word
UInt16 s2 = (UInt16)(System.Convert.ToUInt32(d2) & 0xffff);              //Capture the low word

基本演员表(UInt32)也不起作用。

4 个答案:

答案 0 :(得分:7)

我认为你是在BitConverter课程之后。

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

        float value = 1.1f;
        byte[] bytes = BitConverter.GetBytes(value);
        short upper = BitConverter.ToInt16(bytes, 0);
        short lower = BitConverter.ToInt16(bytes, 2);

答案 1 :(得分:1)

与C方法最接近的直接等价是使用不安全的代码和指针:

private static unsafe void SplitToWords(float f, out ushort s1, out ushort s2)
{
    unsafe
    {
        float* ptr = &f;
        UInt16* s2ptr = (UInt16*) ptr;
        UInt16* s1ptr = s2ptr + 1;

        s1 = *s1ptr;
        s2 = *s2ptr;
    }
}

这可以让你:

public static void Main()
{
    float f = -23984.123f;
    ushort s1;
    ushort s2;
    SplitToWords(f, out s1, out s2);

    Console.WriteLine("{0} : {1}/{2}", f, s1, s2);
    Console.ReadKey();
}

但是,更常见的托管方式是使用BitConverter

byte[] fBytes = BitConverter.GetBytes(f);
s1 = BitConverter.ToUInt16(fBytes, 2);
s2 = BitConverter.ToUInt16(fBytes, 0);

你可以看到这些产生同样的东西:

public static void Main()
{
    float f = -23984.123f;
    ushort s1;
    ushort s2;
    SplitToWords(f, out s1, out s2);

    Console.WriteLine("{0} : {1}/{2}", f, s1, s2);

    byte[] fBytes = BitConverter.GetBytes(f);
    s2 = BitConverter.ToUInt16(fBytes, 0);
    s1 = BitConverter.ToUInt16(fBytes, 2);
    Console.WriteLine("{0} : {1}/{2}", f, s1, s2);

    Console.ReadKey();
}

答案 2 :(得分:1)

简短的回答:不要这样做!

很长的解释:在过去的好时光中,这些黑客已经完成了,因为执行浮动到int转换(反之亦然)比让FPU完成工作更快批次。我可能是错的,但我想我记得PC游戏的这种优化的成功故事Descent(有人记得吗? - 好日子Quake 1天)。在这种情况下,它产生了30%的差异。至少我记得..

现在这已不再适用,事实上情况正好相反。如果您针对旧版x86 FPU编译代码,则必须以整数单位完成任何bit-fiddling,并且必须通过内存完成从float到int单元的每个转换。这需要花费批次的周期。您通常不会混合使用相同值的float和int操作,并且CPU未针对此用例进行优化。

另一方面,如果代码是针对SSE指令集编译的,则可以采用快捷方式。对浮点数据进行整数运算没有额外的成本,反之亦然,但是直接的< - >通过SSE的浮动转换在第一时间更快,所以为什么要这么麻烦?

对于其他架构来说情况要糟糕得多。在ARM Cortex-A8上,例如这样的技巧会使整个CPU停顿至少21个周期......我已经阅读了关于在{{上混合int和float的恐怖故事3}}(加载/修改/存储任何人?)

总结:除非您为Pentium-I传统硬件编写,否则不要这样做。如果是的话,请联系我;我的硬盘驱动器上仍然有所有时序和示例代码。

答案 3 :(得分:0)

有一个类BitConverter,它有一些很好用的方法。

例如,方法GetBytes可以将许多不同类型的变量转换为字节数组,并且方法ToUInt16返回从字节数组中指定位置的两个字节转换的16位无符号整数。 / p>