-1
votes

Le résultat de l'initialisation du flotteur est inattendu

Communauté Visual Studio 2019 La variable de flotteur n'est pas ce que je l'initialise. Je l'ai rendu moins précis dans l'espoir d'éviter la troncature. N'est-ce pas "contrôlable"?

essayé de forcer l'init à tourner d'autres manières xxx xxx

J'avais commencé avec le débogueur et écrit cela pour rencontrer SO reqs. Dans mon cas, le débogueur correspondait aux impressions


6 commentaires

printf produit un texte représentation de la valeur du flotteur. Vérifiez la valeur dans le débogueur si vous souhaitez savoir ce que la CPU pense que la valeur est.


La valeur exacte pour float b = 80.123456F; est 80.1234588623046875.


Vous avez une différence dans le 8ème chiffre significatif, tandis que float est seulement bon pour environ 7. Il existe infiniment de nombreux nombres réels dans la plage couverte par float qui a un stockage fini d'environ 2 ^ 32 valeurs différentes. Donc, la plupart des valeurs réelles doivent être approchées de la valeur exacte la plus proche qui peut être représentée.


Le plus grand numéro IEEE 754 32 32 bit strictement inférieur à 80.1234588623046875 est 80.12345123291015625. Il n'y a pas de magie d'arrondi qui peut obtenir un résultat de flotteur entre ces deux valeurs.


Comment trouver la valeur exacte?


Le convertisseur à point flottant IEEE-754 est un excellent outil pour comprendre ce type de résultats inattendus.


3 Réponses :


0
votes

Les floats ne sont que précis au plus 7 chiffres significatifs. Pas 7 décimal chiffres. 80.123456F a 8 chiffres significatifs, de sorte que cela ne va pas fonctionner.

tandis que 80.12345 n'a que 7 chiffres significatifs, il finit en fait vers 80.1234512329101562. Ce qui, tant que vous n'essayez pas d'imprimer plus de chiffres que cela, c'est d'accord. Malheureusement,% F imprime toujours 6 chiffres après le point décimal. Ce qui, dans ce cas, est un point de vue. Vous feriez un peu mieux avec% G où vous pouvez spécifier un nombre de chiffres significatifs.


4 commentaires

Comment savez-vous que cela "finit vers 80.1234512329101562" si c'est en fait, comment est-ce "seulement 7 chiffres significatifs"? Merci


@CHUP - Nombre de chiffres significatifs spécifiés par le flt_decimal_dig , dbl_decimal_dig et ldbl_decimal_dig macros définis dans float.h . Il s'agit du nombre maximum de chiffres qui sont garanties être des représentations précises pour un type donné ( float , double et long double , respectivement), même si certaines valeurs spécifiques peuvent offrir plus de chiffres de précision. La valeur "réelle" peut être déduite en examinant une représentation binaire de la valeur et en ajoutant manuellement les bits.


1/10 ne peut pas être représenté exactement en binaire. Seules les fractions comme 1/2, 1/4, ... 1/65536 (etc.) peuvent être. Il y a des mathématiques qui vous montreront ce que vous pouvez compter, mais les chiffres fonctionnent à 7 chiffres de précision pour les valeurs de points flottants IEEE.


@Tomtanner John Bode, merci gars, c'est ce que je cherchais



0
votes

Deux numéros:

  • printf avec le spécificateur de conversion % f fait sa propre arrondi de valeurs à virgule flottante pour l'affichage. Vous pouvez contrôler combien de chiffres après le point décimal sont affichés à l'aide d'un spécificateur de précision: printf ("% .8f \ n", b); imprimera jusqu'à 8 chiffres après le point décimal, et printf ("% .16f \ n", a); imprimera 16. Ne faites pas confiance à cette valeur affichée, car ...

  • Un nombre infini de valeurs réelles ne peut pas s'intégrer dans un nombre fini de bits, de sorte que la plupart des valeurs réelles ne peuvent pas être représentées exactement - vous obtenez une approximation qui est seulement bonne à de nombreux chiffres décimaux . Simple précision float Les types ne garantissent pas beaucoup plus de 6 à 7 chiffres décimaux de précision (ce n'est pas seulement le nombre de chiffres suivant le point décimal, c'est Nombre total de chiffres ). double vous donne quelque chose comme 10 à 11 chiffres. Si vous devez représenter des valeurs avec de nombreux chiffres de précision (plus de 12 ou plus), vous avez besoin de passer des types de points flottants natifs et d'utiliser une bibliothèque de précision tierce.


0 commentaires

0
votes

La solution à ce problème peut être de modifier les types de données. Même si double fonctionne de la même manière que float , approximation d'une large gamme de nombres réels par un ensemble fini de rationnelles, les doubles sont si proches que l'erreur d'arrondi est moins susceptible de compter.

Par exemple, les valeurs float les plus proches du nombre réel 80.123456 sont 80.12345123291015625 et 80.1234588623046875. Les valeurs double les plus proches de 80.123456 sont 80.123456000000004451067070476710796356201171875 et 80.1234559999999902402123552747070789337158203125.

float a ses utilisations, dans des situations dans lesquelles vous traitez de très grands ensembles de nombres de très faibles de précision, mais double est le type le plus utile. Lorsque vous obtenez une quantité physique dans un programme utilisant double , l'erreur de mesure dépasse l'erreur d'arrondi.


0 commentaires