6
votes

Conversion 'Float' en 'octet [4]' et retour à "flotteur" dans .NET Micro Cadre

Quel est le meilleur moyen de convertir un float à un octet <4] puis retour à un "flotteur"?

Je fais cela dans c # .NET Micro Framewy , donc il n'y a pas < Code> Bitconverter Disponible pour mon utilisation.


9 commentaires

Soyez prudent de l'endianness (le lien de @Mitch montre une classe BitConverter qui utilise Little Endian)


La plate-forme qui code le float n'a aucune sorte de classe BitConverter. Rien qui utilise une classe Bitconverter de tout type fonctionnera.


Néanmoins, on dirait que c'est une source ouverte, je peux simplement extraire les morceaux dont j'ai besoin.


Ces flotteurs sont maintenant des diamants.


Jusqu'à présent, rien que j'ai essayé n'a vraiment travaillé. Quelqu'un peut-il suggérer une réponse qui utilise des opérations bits pure?


Je suppose que vous avez essayé la classe du lien mentionné précédemment (aurait été écrit pour C # .NETMF). S'il vous plaît expliquer comment cela n'a pas fonctionné: quelles fonctions avez-vous essayées? Et qu'attendez-vous de la production?


Je ne peux pas l'utiliser car ces octets sont échangés entre deux cibles. Dont l'un n'est pas en cours d'exécution NetMF. Ils sont codés sur un et décodés de l'autre. L'autre cible est un arduino.


Vous pourriez avoir une inadéquation d'endansion; On est codé dans peu d'Endian tandis que l'autre décodage dans Big Endian. Vous devrez modifier la classe pour permettre la spécification de l'endansnitive et choisir la même endansion sur les deux plates-formes.


@Jimmy de tout le non-sens. Je suis sur un cheval.


3 Réponses :


2
votes

J'ai modifié la classe bitconverter code> de Une implémentation de Netduino pour permettre la spécification de l'endansement (ce n'est pas le "meilleur moyen", mais ça marche). Si le tableau d'octets est envoyé sur le réseau, j'utiliserais bigendien code>. Juste un rappel que dangereux code> n'est pas officiellement pris en charge sur 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 commentaires

10
votes

La conversion de uint code> à float code> (et inverser) peut être effectuée avec un code "Safe" (bien que je ne sais pas si cela est possible sur le NETMF ou non).

[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 commentaires

Cela fait-il une différence si l'autre variable est un UINT ou INT?



-1
votes

Cela a fonctionné pour moi, peut ne pas être la réponse la plus complète mais simple xxx


1 commentaires

Ce n'est même pas C #!