Quelles sont les bonnes choses à faire et à ne pas faire en arithmétique en virgule flottante (IEEE754 en cas de confusion) pour assurer une bonne stabilité numérique et une grande précision des résultats?
Je sais que certains, par exemple, ne soustraient pas des quantités de magnitude similaire, mais je suis curieux de savoir quelles autres bonnes règles existent.
Tout d’abord, entrez dans l’idée que les nombres en virgule flottante NE suivent PAS nécessairement les mêmes règles que les nombres réels … une fois que vous avez accepté cela, vous comprendrez la plupart des pièges.
Voici quelques règles / conseils que j’ai toujours suivis:
if (myFloat == 0)
(a + b) + c != a + (b + c)
La règle n ° 1 “ne pas” avec les nombres à virgule flottante est:
N’utilisez pas de nombres à virgule flottante où les entiers suffiront.
Comprenez comment se comporte la virgule flottante.
NE croyez PAS que de simples règles suffiront pour les utiliser correctement.
Par exemple, au moins deux réponses ont proposé d’interdire la comparaison de la virgule flottante à l’égalité. Il existe d’abord des cas où il est nécessaire de les comparer pour obtenir l’égalité. Ensuite, lorsque vous avez besoin de vérifier la distance, vous devez également être conscient du fait que le piège est son piège. Par exemple, il n’est pas transitif, propriété que la plupart des gens assumeront comme test d’égalité.
N’oubliez pas qu’en raison d’une arithmétique en virgule flottante défectueuse, des personnes sont mortes et des milliards de dollars de dommages sont survenus.
ne jamais essayer de faire une comparaison d’égal à égal
double da, db;
…
si (da == db) alors quelque chose.
rappelez-vous que C utilise le double par défaut, donc si vous voulez faire une simple précision, soyez clair à ce sujet
float fa, fb;
…
fa = fb + 1,0;
va convertir fb en double faire un double append puis convertir en simple et faire un seul égal
Au lieu
fa = fb + 1,0F.
tous célibataires.
Si vous comptez utiliser un nombre entier tel que 1.0, n’en faites pas une décimale dans votre code. vous obtenez plus de fiabilité de vos compilateurs / outils si vous pouvez minimiser les nombres ASCII. alors
fa = fb + 1;
ou au lieu de
fa = fb + 0,3333333F;
faites quelque chose comme ça (si vous êtes intéressé par la précision).
fc = 1; fc = fc / 3; fa = fb + fc;
Beaucoup, beaucoup de choses, la virgule flottante est douloureuse, les compilateurs et les bibliothèques ne sont pas très bons, les fpus ont des bogues et l’IEEE est exceptionnellement douloureux et conduit à plus de bogues. Malheureusement, c’est le monde dans lequel nous vivons sur la plupart des plateformes.
Mon “arme principale” pour éviter les pièges en virgule flottante consiste à bien comprendre leur façon de travailler. Je pense que Chris Hecker explique assez bien les bases.
Recherchez, téléchargez et lisez “ce que tout informaticien devrait savoir sur l’arithmétique en virgule flottante”