2010-04-28 4 views
3

J'ai un fichier binaire de doubles que j'ai besoin de charger en utilisant C++. Cependant, mon problème est qu'il a été écrit en format big-endian mais l'opérateur fstream >> lira alors le numéro erroné car ma machine est little-endian. Cela semble être un problème simple à résoudre pour les entiers, mais pour les doubles et les flottants, les solutions que j'ai trouvées ne fonctionneront pas. Comment puis-je (ou devrais-je) résoudre ce problème?Pourquoi l'échange d'octets à virgule flottante est-il différent de l'échange d'octets sur un nombre entier?

Je lis comme référence pour la permutation d'octet entier:
How do I convert between big-endian and little-endian values in C++?

EDIT: Bien que ces réponses sont éclairantes, j'ai trouvé que mon problème est avec le fichier lui-même et non le format du fichier binaire Les données. Je crois que mon échange d'octets fonctionne, j'avais juste des résultats confus. Merci de votre aide!

+0

Je me serais attendu à double/float solutions de permutation octet fonctionne exactement le même (qui est, définir une union flottante/int32, écrire le flotteur mal-endian en elle, octet swap, le int32, et lire le flotteur à nouveau), donc je pense que vous devez expliquer quelles sont les solutions que vous avez essayées et qui ne fonctionneront pas. –

Répondre

6

Le moyen le plus portable est de sérialiser en format textuel afin de ne pas avoir de problèmes d'ordre des octets. C'est ainsi que fonctionne operator>> donc vous ne devriez pas avoir de problèmes endian avec >>. Le principal problème avec les formats binaires (qui expliquerait les problèmes d'endian) est que les nombres à virgule flottante sont constitués d'un nombre de bits de mantisse, d'un nombre de bits d'exposant et d'un bit de signe. L'exposant peut utiliser un décalage. Cela signifie qu'un réordonnancement d'octets droits peut ne pas être suffisant, en fonction du format de la source et de la cible. Si vous utilisez et IEEE-754 sur les deux machines alors vous pouvez être OK avec une inversion d'octets directs car cette norme spécifie un format d'échange de chaîne de bits qui devrait être portable (questions d'ordre des octets de côté). Si vous devez convertir entre deux architectures machine et que vous devez utiliser une mémoire tampon d'octets bruts, alors tant que le format numérique de base est le même (ie ils ont le même nombre de bits dans chaque partie du nombre) , vous pouvez lire les données dans un tableau de unsigned char, utiliser des routines d'échange d'octets et de bits de base pour corriger le format de stockage, puis copier les octets bruts dans une variable du type approprié.

+0

Vous ne devez pas sérialiser dans un format textuel - vous pouvez convertir un nombre à virgule flottante en trois entiers (signe, mantisse et exposant) en utilisant une méthode orientée sur la valeur plutôt que sur la représentation, puis sérialiser ces entiers en octets réseau commander de la manière habituelle. – caf

+0

Je suis curieux: y-a-t-il des puces qui ne sont pas courantes et qui ne sont pas IEEE-754? – Will

+0

@caf: Vous pouvez ignorer une étape et les convertir en deux valeurs: mantisse et exposant signés. Mais la manière standard de (dé) sérialiser dans l'ordre des octets du réseau mérite une réponse. – Potatoswatter

0

Les opérateurs de conversion standard ne fonctionnent pas avec les données binaires, vous ne savez donc pas comment vous vous trouvez. Cependant, comme l'échange d'octets fonctionne sur des octets, pas sur des nombres, vous l'effectuez sur des données destinées à être flottantes, tout comme des données qui seront des entiers.

Et puisque le texte est si inefficace et les ensembles de données à virgule flottante ont tendance à être si grand, il est tout à fait raisonnable de vouloir cela.

int32_t raw_bytes; 
stream >> raw_bytes; // not an int, just 32 bits of bytes 
my_byte_swap(raw_bytes); // swap 'em 
float f = * reinterpret_cast< float * >(& raw_bytes); // read them into FPU 
Questions connexes