Comparer les flottants dans leurs représentations de bits

Disons que je veux une fonction qui prend deux floats ( x et y ) et que je veuille les comparer en utilisant non pas leur représentation float mais plutôt leur représentation au niveau du bit comme un unsigned int 32 bits. C’est-à-dire qu’un nombre tel que -495.5 a la représentation binary 0b11000011111001011100000000000000 ou 0xC3E5C000 comme float , et j’ai un unsigned int avec la même représentation binary (correspondant à une valeur décimale 3286614016 , qui ne me dérange pas). Existe-t-il un moyen simple d’effectuer une opération telle que <= sur ces flotteurs en utilisant uniquement les informations contenues dans leurs homologues respectives unsigned int ?

Vous devez faire une comparaison signée à moins de vous assurer que toutes les valeurs d’origine étaient positives. Vous devez utiliser un type entier de même taille que le type à virgule flottante d’origine. Chaque puce peut avoir un format interne différent, de sorte que la comparaison des valeurs de puces différentes sous forme d’entiers est susceptible de donner des résultats trompeurs.

La plupart des formats float ressemblent à ceci: sxxxmmmm

s est un bit de signe
xxx est un exposant
mmmm est la mantisse

La valeur représentée sera alors quelque chose comme: 1mmm << (xxx-k)

1mmm car il y a un premier bit implicite, sauf si la valeur est zéro.

Si xxx < k alors ce sera un changement à droite. k est proche de la moitié de la plus grande valeur pouvant être exprimée par xxx mais n’est pas égal à celle-ci. Il est ajusté à la taille de la mantisse.

Autant dire que, sans NaN , comparer des valeurs à virgule flottante à des entiers signés de la même taille donnera des résultats significatifs. Ils sont conçus de cette manière pour que les comparaisons en virgule flottante ne soient pas plus coûteuses que les comparaisons entières. Il existe des optimisations du compilateur pour désactiver les contrôles NaN afin que les comparaisons soient des comparaisons entières droites si le format à virgule flottante de la puce le prend en charge.

En tant que nombre entier, NaN est supérieur à l'infini supérieur aux valeurs finies. Si vous essayez une comparaison non signée, toutes les valeurs négatives seront plus grandes que les valeurs positives, tout comme les entiers signés convertis en non signés.

En un mot, non. IEEE 754 peut autoriser certains types de piratage de ce type, mais ils ne fonctionnent pas tout le temps et traitent tous les cas. Certaines plates-formes n’utilisent pas cette norme de virgule flottante (comme les doublons sur x87 avec une précision de 80 bits en interne).

Si vous faites cela pour des raisons de performances, je vous suggère de reconsidérer votre décision. S’il est plus rapide d’utiliser la comparaison d’entiers, le compilateur le fera probablement pour vous, et si ce n’est pas le cas, vous payez plusieurs fois pour une conversion float en int, quand une simple comparaison peut être possible sans déplacer les flotteurs des registres.

Si vous ne vous souciez vraiment pas du rendement de la conversion, ce n’est pas si difficile. Mais les résultats sont extrêmement non portables, et vous ne recevrez certainement pas un ordre qui ressemblerait du tout à ce que vous obtiendriez en comparant directement les flottants.

 typedef unsigned int TypeWithSameSizeAsFloat; //Fix this for your platform bool compare1(float one, float two) union Convert { float f; TypeWithSameSizeAsFloat i; } Convert lhs, rhs; lhs.f = one; rhs.f = two; return lhs.i < rhs.i; } bool compare2(float one, float two) { return reinterpret_cast(one) < reinterpret_cast(two); } 

Comprenez simplement les mises en garde et choisissez votre deuxième type avec soin. En tout cas, c’est un excersize presque sans valeur.

Peut-être que je comprends mal la question, mais je suppose que vous pourriez faire ceci:

 bool compare(float a, float b) { return *((unsigned int*)&a) < *((unsigned int*)&b); } 

Mais cela suppose toutes sortes de choses et justifie également la question de savoir pourquoi vous souhaitez comparer les représentations au niveau des bits de deux flottants.