2011-01-20 8 views
6

¿Cuál es la mejor forma de convertir un float en un byte[4] y luego volver a un 'float'?Convirtiendo 'float' en 'byte [4]' y volviendo a 'float' en .NET Micro Framework

Estoy haciendo esto en C# .NET Micro Framework, por lo que no hay BitConverter disponible para mi uso.

+1

tener cuidado de orden de bytes (el enlace desde @Mitch muestra una clase que utiliza BitConverter little endian) –

+1

La plataforma que codifica que el flotador no tiene ningún tipo de clase BitConverter. Nada que use una clase BitConverter de ningún tipo funcionará. – chris12892

+0

No importa, parece que es de código abierto, puedo extraer los bits que necesito. – chris12892

Respuesta

2

He modificado la clase BitConverter de a Netduino implementation para permitir la especificación de endianness (no es la "mejor manera", pero funciona). Si la matriz de bytes se envía a través de la red, usaría BigEndian. Solo un recordatorio de que unsafe no es oficialmente compatible con 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(); 
     } 
    } 
} 
9

La conversión de uint a float (y hacia atrás) se puede hacer con el código "seguro" también (aunque no sé si esto es posible en el NETMF o no).

[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; 
} 
1

Esto funcionó para mí, no puede ser la respuesta más completa, pero sencilla

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; 
}