Converting 'float' to 'byte[4]' and back to 'float' in .NET Micro Framework

后端 未结 3 1674
清歌不尽
清歌不尽 2020-12-06 13:17

What\'s the best way to convert a float to a byte[4] and then back to a \'float\'?

I am doing this in C# .NET Micro Framework, so there is

相关标签:
3条回答
  • 2020-12-06 14:01

    I've modified the BitConverter class from a Netduino implementation to allow endianness specification (it's not the "best way", but it works). If the byte array is sent over the network, I would use BigEndian. Just a reminder that unsafe is not officially supported in 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();
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-06 14:08

    This worked for me, may not be the most complete answer but simple

    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;
    }
    
    0 讨论(0)
  • 2020-12-06 14:09

    The conversion from uint to float (and reverse) can be done with "safe" code as well (though I don't know if this is possible on the NETMF or not).

    [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;
    }
    
    0 讨论(0)
提交回复
热议问题