Pourquoi devrais-je utiliser le complément à 2 pour comparer deux doubles au lieu de comparer leurs différences à une valeur epsilon?

StackOverflow https://stackoverflow.com/questions/96233

  •  01-07-2019
  •  | 
  •  

Question

Référencé ici et here ... Pourquoi utiliser un complément de deux sur une méthode epsilon? Il semble que la méthode epsilon conviendrait dans la plupart des cas.

Mise à jour: je recherche uniquement une raison théorique pour laquelle vous utiliseriez l'une sur l'autre. J'ai toujours utilisé la méthode epsilon.

Quelqu'un at-il utilisé la comparaison du complément à 2 avec succès? Pourquoi? Pourquoi pas?

Était-ce utile?

La solution

le deuxième lien auquel vous faites référence mentionne un article qui décrit assez longuement le problème:

http://www.cygnus-software.com/papers/comparingfloats /comparingfloats.htm

mais à moins que vous ne modifiiez les performances, je resterais avec epsilon afin que les gens puissent déboguer votre code

Autres conseils

La méthode des bits pourrait être plus rapide. Je dis peut-être parce que, sur les processeurs modernes (multicœurs, hautement en pipeline), il est souvent impossible de deviner ce qui est vraiment plus rapide. Codez la mise en œuvre la plus simple, la plus évidemment correcte, puis mesurez, puis optimisez.

En résumé, lorsque vous comparez deux flotteurs d'origines inconnues, il est presque impossible de choisir un epsilon valide.

Par exemple:

Qu'est-ce qu'un bon epsilon lorsque l'on compare la distance en miles entre Atlanta GA, Dallas TX et un lieu de l'Ohio?

Qu'est-ce qu'un bon epsilon lorsque l'on compare la distance en miles entre mon pied gauche, mon pied droit et l'ordinateur sous mon bureau?

EDIT:

D'accord, bon nombre de personnes ne comprennent pas pourquoi vous ne savez pas ce qu'est votre epsilon.

À l’époque des traditions, j’ai écrit deux programmes qui fonctionnaient avec NeverWinter Nights (un jeu créé par BioWare). L'un des programmes a pris un modèle binaire et l'a converti en ASCII. L'autre programme a pris un modèle ASCII et l'a compilé en binaire. L'un des tests que j'ai écrit consistait à prendre tous les modèles binaires de BioWare, à les décompiler en ASCII, puis à revenir en binaire. Ensuite, j'ai comparé ma version binaire avec la version originale de BioWare. Lors de la comparaison, l’un des problèmes rencontrés a été la gestion de certaines des légères variations des valeurs en virgule flottante. Ainsi, au lieu de proposer différentes EPSILONS pour chaque type de nombre à virgule flottante (sommet, normale, etc.), je souhaitais utiliser quelque chose comme cette comparaison de complément à deux. Cela évite ainsi l’ensemble des multiples problèmes liés à EPSILON.

Le même type de problème peut s'appliquer à tout type de logiciel qui traite des données tierces et doit ensuite valider leurs résultats avec l'original. Dans ces cas, vous pourriez même ne pas savoir ce que représentent les valeurs en virgule flottante, il vous suffit de les comparer. Nous avons rencontré ce problème avec notre logiciel d'automatisation industrielle.

EDIT:

LOL, cela a été voté de haut en bas par différentes personnes.

Je vais résumer le problème à ceci, étant donné deux nombres à virgule flottante arbitraires , comment décidez-vous quel epsilon utiliser? Tu ne peux pas.

Comment pouvez-vous comparer 1e23 et 1.0001e23 avec un epsilon tout en comparant 1e-23 et 5.2e-23 avec le même epsilon? Bien sûr, vous pouvez faire quelques trucs epsilon dynamiques, mais c’est tout le sens de la comparaison d’entiers (ce qui n'exige PAS que les entiers soient exacts).

La comparaison d’entiers permet de comparer deux flottants en utilisant un epsilon par rapport à la magnitude des nombres.

MODIFIER

Steve, regardons ce que vous avez dit dans les commentaires:

"Mais vous savez ce que l'égalité signifie pour vous ... Vous devriez donc pouvoir trouver un epsilon approprié".

Retournez cette déclaration pour dire:

"Si vous savez ce que l'égalité signifie pour vous, vous devriez être en mesure de trouver un epsilon approprié."

Ce que je veux dire, c’est qu’il existe des applications dans lesquelles nous ne savons pas ce que l’égalité signifie au sens absolu. Nous devons donc recourir à une comparaison relative qui correspond à ce que la version entière essaie de faire. faire.

Pour ce qui est de la vitesse, suivez ces règles:

  1. Si vous n'êtes pas un développeur très expérimenté, n'optimisez pas.
  2. Si vous êtes un développeur expérimenté, n'optimisez pas encore.

Faites la méthode la plus simple.

Alex

Oskar a raison. Ne vis pas avec ça sauf si tu as vraiment, vraiment besoin de cette performance.

Et vous ne le faites pas. Si vous étiez dans la même situation, vous n'auriez pas eu à poser la question - vous le sauriez déjà. Si vous pensez le faire, alors vous ne le faites pas. Vos problèmes de performance sont ailleurs. Utilisez simplement la version lisible.

L'utilisation de toute méthode qui compare bit par bit entraînera des problèmes lorsque les fractions sont représentées par des approximations. Tous les nombres en virgule flottante dont les fractions ne sont pas exprimées en puissances de deux (1/2, 1/4, 1/8, 1/65536, & c) sont approximés. Donc, bien sûr, tous les nombres sont irrationnels.

float third = 1/3; float deux = 2,0; float autre_deux = troisième * 6.0; si (deux! = un autre_deux)    print ("Approximation! \ n");

La comparaison bit par bit ne fonctionne que lorsque vous dérivez les nombres en virgule flottante de la même manière ou qu’ils sont des représentations exactes (nombres entiers, puissances de fraction de deux). Même dans ce cas, il peut y avoir plusieurs représentations de certains nombres, bien que je ne l’aie jamais vu dans un système en fonctionnement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top