47 votes

Comment modifier un float par son plus petit incrément (ou presque)?

J'ai un double valeur f et comme un moyen de déplacer très légèrement plus grand (ou plus petit) pour obtenir une nouvelle valeur qui sera aussi proche que possible de l'original, mais toujours strictement supérieur (ou inférieur) à l'original.

Il n'a pas à être fermer pour le dernier bit-c'est plus important que tout ce changement que j'ai fait est garanti pour produire une valeur différente et ne pas arrondir le dos de l'original.

62voto

Nils Pipenbrinck Points 41006

Vérifier vos calculs.h fichier. Si vous êtes chanceux, vous avez l' nextafter et nextafterf fonctions définies. Ils font exactement ce que vous voulez dans un portable et indépendant de la plateforme, et qui sont une partie du standard C99.

Une autre façon de faire (peut-être une solution de secours) est de décomposer votre flotter dans la mantisse et l'exposant de la partie. L'incrémentation est facile: il suffit d'en ajouter un à la mantisse. Si vous obtenez un dépassement de capacité que vous avez à gérer cela par incrémentation de votre exposant. La décrémentation fonctionne de la même manière.

EDIT: Comme l'a souligné dans les commentaires, il suffit d'incrémenter seulement le flotteur dans sa représentation binaire. La mantisse de dépassement de l'incrémenter l'exposant, et c'est exactement ce que nous voulons.

C'est en un mot la même chose que nextafter n'.

Ce ne sera pas complètement portable si. Vous avez à traiter avec endianess et le fait que toutes les machines n'ont IEEE flotteurs (ok - la dernière raison est plus académique).

Également la manipulation NAN et infinite peut-être un peu délicat. Vous ne pouvez pas, il suffit d'incrémenter ce qu'ils sont, par définition, pas des numéros.

7voto

simon Points 5346

Vous avez eu certains des conseils spécifiques à ce cas déjà, mais en plus --- si vous ne l'avez pas déjà, je vais vous invitons à lire Ce que Chaque Ordinateur Scientifique Doit Savoir à Propos de l'Arithmétique à virgule Flottante. En va de même pour quelqu'un d'autre lecture de ce fil qui est incertain de la façon dont ils doivent gérer des flotteurs, vraiment. Il est bien écrit, et efface commun un certain nombre d'idées fausses à propos de virgule flottante représentation.

5voto

moonshadow Points 28302

En termes absolus, le plus petit montant que vous pouvez ajouter à une valeur à virgule flottante en faire une nouvelle distincte de la valeur dépendra de l'ampleur actuelle de la valeur, il sera le type de la machine epsilon multipliée par le courant de l'exposant.

Découvrez la spécification IEEE pour virgule flottante represenation. La façon la plus simple serait de réinterpréter la valeur comme de type entier, ajouter 1, puis cochez (si vous aimez) que vous n'avez pas retourné le signe ou généré un NaN en examinant le signe et les bits d'exposant.

Sinon, vous pouvez utiliser frexp pour obtenir le courant de la mantisse et de l'exposant, et donc de calculer une valeur à ajouter.

4voto

Jon Skeet Points 692016

Je ne sais pas dans le C et le C++, mais si vous pouvez convertir le raw bits d'un entier (l'équivalent de Convertir.DoubleToInt64Bits dans .NET) puis incrémenter le nombre entier, puis de les convertir en arrière encore une fois, c'est votre réponse - en supposant que le processeur utilise la norme IEEE 754. Le format de l'IEEE est très astucieusement conçu de sorte que si vous trier une collection de nombres à virgule flottante en les traitant comme des entiers, vous obtenez le bon ordre.

Désolé c'est seulement la moitié de la réponse, mais j'espère que ça va pointer dans la bonne direction. Mon C/C++ est rouillé, mais vous pouvez être en mesure d'utiliser:

long *x = &f;
(*x)++;

ou quelque chose de similaire. Vaut la peine d'essayer et vérifier avec quelqu'un de plus sur la balle :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X