【问题标题】:Converting 'float' to 'byte[4]' and back to 'float' in .NET Micro Framework在 .NET Micro Framework 中将“float”转换为“byte[4]”并返回“float”
【发布时间】:2011-01-20 02:25:38
【问题描述】:

float 转换为byte[4] 然后再转换回“浮点数”的最佳方法是什么?

我在 C# .NET Micro Framework 中执行此操作,因此没有可用的 BitConverter 可供我使用。

【问题讨论】:

  • 小心字节序(@Mitch 的链接显示了一个使用小字节序的 BitConverter 类)
  • 对浮点数进行编码的平台没有任何类型的 BitConverter 类。使用任何类型的 BitConverter 类都不行。
  • 没关系,看起来它是开源的,我可以提取我需要的部分。
  • 这些花车现在是钻石。
  • 到目前为止,我所尝试的一切都没有真正奏效。谁能提出一个使用纯按位运算的答案?

标签: c# embedded .net-micro-framework


【解决方案1】:

uintfloat(和反向)的转换也可以使用“安全”代码完成(尽管我不知道这是否可以在 NETMF 上实现)。

[StructLayout(LayoutKind.Explicit)]
struct UIntFloat
{       
    [FieldOffset(0)]
    public float FloatValue;

    [FieldOffset(0)]
    public uint IntValue;        
}

public static float ToSingle(byte[] value, int index)        
{           
    uint i = ToUInt32(value, index);            
    return ToSingle(i);
}

public static float ToSingle(uint value)
{
    UIntFloat uf = new UIntFloat();
    uf.IntValue = value;
    return uf.FloatValue;
}

【讨论】:

  • 如果另一个变量是 uint 或 int 有什么区别吗?
【解决方案2】:

我已从 a Netduino implementation 修改了 BitConverter 类以允许字节顺序规范(这不是“最佳方式”,但它有效)。如果字节数组是通过网络发送的,我会使用BigEndian。只是提醒一下unsafe 在 NETMF 中不受官方支持。

using System;
using System.Diagnostics;

namespace netduino
{
    public static class BitConverter
    {
        public static byte[] GetBytes(uint value)
        {
            return new byte[4] { 
                    (byte)(value & 0xFF), 
                    (byte)((value >> 8) & 0xFF), 
                    (byte)((value >> 16) & 0xFF), 
                    (byte)((value >> 24) & 0xFF) };
        }

        public static unsafe byte[] GetBytes(float value)
        {
            uint val = *((uint*)&value);
            return GetBytes(val);
        }

        public static unsafe byte[] GetBytes(float value, ByteOrder order)
        {
            byte[] bytes = GetBytes(value);
            if (order != ByteOrder.LittleEndian)
            {
                System.Array.Reverse(bytes);
            }
            return bytes;
        }

        public static uint ToUInt32(byte[] value, int index)
        {
            return (uint)(
                value[0 + index] << 0 |
                value[1 + index] << 8 |
                value[2 + index] << 16 |
                value[3 + index] << 24);
        }

        public static unsafe float ToSingle(byte[] value, int index)
        {
            uint i = ToUInt32(value, index);
            return *(((float*)&i));
        }

        public static unsafe float ToSingle(byte[] value, int index, ByteOrder order)
        {
            if (order != ByteOrder.LittleEndian)
            {
                System.Array.Reverse(value, index, value.Length);
            }
            return ToSingle(value, index);
        }

        public enum ByteOrder
        {
            LittleEndian,
            BigEndian
        }

        static public bool IsLittleEndian
        {
            get
            {
                unsafe
                {
                    int i = 1;
                    char* p = (char*)&i;

                    return (p[0] == 1);
                }
            }
        }
    }
}

namespace BitConverterTest
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] msbFirst = new byte[] { 0x42, 0xF6, 0xE9, 0xE0 };
            byte[] lsbFirst = new byte[] { 0xE0, 0xE9, 0xF6, 0x42 };
            const float f = 123.456789F;

            byte[] b = netduino.BitConverter.GetBytes(f, netduino.BitConverter.ByteOrder.BigEndian);
            for (int i = 0; i < b.Length; i++)
            {
                Debug.Assert(msbFirst[i] == b[i], "BitConverter.GetBytes(float, BigEndian) i=" + i);
            }

            Debug.Assert(f == netduino.BitConverter.ToSingle(msbFirst, 0, netduino.BitConverter.ByteOrder.BigEndian));

            Console.WriteLine("All tests passed");
            Console.ReadKey();
        }
    }
}

【讨论】:

    【解决方案3】:

    这对我有用,可能不是最完整的答案,但很简单

    void floatToByte(GLubyte b[], float n)
    {
    unsigned int val = *((unsigned int*)&n);
    
    b[0] = (GLubyte)(val  & 0xFF);
    b[1] = (GLubyte)((val >> 8) & 0xFF);
    b[2] = (GLubyte)((val >> 16) & 0xFF);
    b[3] = (GLubyte)((val >> 24) & 0xFF);   
    }
    
    
    
    float byteToFloat(GLubyte b[])
    {
    unsigned int ret =  (unsigned int)(b[0] << 0 | b[1] << 8 | b[2] << 16 | b[3] << 24);
    float r = *(((float*)&ret));
    return r;
    }
    

    【讨论】:

    • 这甚至不是 C#!
    猜你喜欢
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 2011-12-17
    • 2018-04-05
    • 2011-06-17
    • 1970-01-01
    • 2022-01-03
    相关资源
    最近更新 更多