• # Ecrire du code avec des flottants

    Posté par . En réponse au journal Comment les programmeurs écrivent du code flottant ?. Évalué à 10.

    Une petite question métaphysique m'a traversé l'esprit ce soir : Comment les codeurs codent avec du code flottant ?

    Réponse de gascon : Ca dépend du code.
    En fait il y a plusieurs cas de figures :
    - Ranapété : Je me fous de ce que font les flottants dans la mesure ou ils me donnent un résultat suffisament juste rapidement. C'est le cas par exemple en programmation 3D (ou on peut toujours s'arranger à posteriori pour éliminer les cas problématiques en corrigeant les cartes ou les modèles 3D
    Par exemple la plupart des moteurs de Carmak ont de gros problèmes de Z aliasing, mais ca ne se voit pas sur les cartes car les cas à problème sont soigneusement évités) C'est aussi le cas dans évaluation biologique (ou la norme sanitaire est entre 10 at 1000 fois inférieure à la dose toxique, donc on se moque un peu de savoir si on a 0,0800 μg de saleté ou 0,07999954215 ) et dans la plupart des calculs fait à partir de prélèvement capteurs en temps réel (le capteur a une précision de 0,01 alors le 17ème chiffre après la décimale est de toutes les façons faux)

    - Ranapété du moment que ca concorde : Là je me moque de savoir ce que font les décimales parceque 1°) de toutes les façon au final je vais arrondir 2°) j'ai largement assez de précision pour m'en sortir et/ou 3°) de toutes les façon je suis sur des valeurs qui fluctuent tellement que je vais me mettre d'accord avec un tiers et qu'on va fixer ensemble un résultat de connivence. Tout ce qui m'interesse c'ets qu'à la fin de la journée j'ai des résultat cohérent avec mes choix et vérifiables par une authorité.
    par exemple une comptabilité en francs que je veux passer en euros. Il faut juste que la somme de toutes mes opérations converties en euros soit égale au réel des comptes converti en euros. En d'autres termes si Somme(Ai)=B je veux Somme(conv(Ai))=conv(B) avec une fonction de converion conv() qui soit identique d'un coté et de l'autre de l'opération et qui soit normalisée et approuvée par un organisme de controle le cas échéant. C'est ce qui se passe dans les chambres de compensation internationales quand les entiers à décimales fixées commencent à plus en pouvoir (additionner des centainnes de milliers d'opérations au dix-milième d'euros près ca devient coton)

    - Ca serait bien que deux ordinateurs différents trouvent le même résultat.
    La le truc c'est pas vraiment que l'on veuille que résultat soit super précis, on veut juste qu'il soit vérifiable. En d'autres termes si une suite de calculs donne come résultat 0.73244298 ca serait bien que la même suite d'opération donne le même résultat sur l'ordinateur d'a coté. Pourquoi ? parceque ca permet de savoir que l'on est pas en train d'atteindre une condition limite (genre quand on trouve des résultats trop différents d'un ordinateur à l'autre, il est temps de changer d'algorithme), ca permet de vérifier qu'un ordi n'est pas en train de rendre l'ame (tiens ca fait quatre fois que l'ordi 1 trouve un résultat qui diverge, apelle le broker je signe le certificat de décès) ou qu'un bit d'execution ou de données n'a pas été perturbé par un effet magnétique farceur (rarissime mais réel sur terre, plus courant dans les satellites et autres engins spatiaux) etc. C'est là que les IEEE rentrent en ligne de compte en faisant un choix abitraire parfois faux, mais vérifiable.

    - 100% pure vraies décimales dedans. Là il s'agit de ne pas faire d'erreur d'arrondi du tout. En d'autres termes l'arrondi n'est fait que sur la dernière décimale stoquée et seulement au moment de stoquer le résultat final. C'est là que les entiers 64 bits calculés sur 80 bits rendent bien service. En d'autres termes on rentre des chiffres exacts avec une précision x, tous les calculs sont faits en précision y (y > x) suffisament grande pour qu'il n'y ait pas de perte d'information avant que les calculs ne soient finis. Et quand les calculs sont finis on repasse en précision x avec un arrondi dans les règles de l'art. Là le boulot du programmeur et de vérifier que l'on ne peut pas perdre d'information dans les opérations avant la sortie du résultat. C'est ce que l'on a dans les calculs par éléments finis simple, ou dans les simulations moléculaires limitées a quelques atomes/molécules. Ce qui nous ammène a l'utilisation la plus chiante des flottants :

    - Bonjour, j'additionne des fourmis avec des éléphants.
    Là on a des trucs du style 45E32 + 0.1E-14 + 0.2E-12 + 0.4E-12 + ... (plusieurs centaines de millions de nombre à faible exposant) ...+ 0.7E-11
    Laissé à lui même avec des arrondis classiques l'ordinateur donnera un résultat très différents suivant l'ordre dans lequel il effectuera les opération.
    Dans pas mal de cas on peut s'en sortir de façon élégante en prioritisant les opérations. C'est à dire en n'essayant d'éviter de faire des opérations entre des nombres qui ne sont pas du même ordre. En d'autres termes on garde l'unité flottante du processeur, mais on lui passe les opérations dans le bon ordre pour que ca se passe bien. Dans les autres cas il faut faire autrement. Par exemple faire appel à des bibliothèques extérieures boostées, faire mumuse avec les registres, la carry et les différents flags soi-même ou passer par des modes de calculs différents (en passant sur des entiers très long ou en utilisant des fonctions vectorielles ou encore ou faisant les opérations sur des "blocs" de précisions différentes que l'on récolle à la fin.)

    Bref, ca dépend du problème à résoudre. De façon générale les calculs en flottants sont casse-pieds, on évite donc autant que possible. Et quand on est obligé de s'en servir (pour des raisons de vitesse ou de précision) on ne surveille les décimales que si on en a vraiment, vraiment besoin.