2016-08-30 1 views
1

Le code suivant:Comment multiplier le point flottant dans ANSI C?

float numberForFactorial; 
    float floatingPart = 1.400000; 
    int integralPart = 1; 

    numberForFactorial = ((floatingPart) - (float)integralPart) * 10; 

    printf("%d", (int)numberForFactorial); 

Retours 3 au lieu de 4. Pouvez-vous me expliquer pourquoi?

+0

Probablement parce que '1.40000' est stocké en interne sous la forme' 1.399999' ou quelque chose comme ça. '(int) 3.99999' est' 3', comme prévu. –

+0

Qu'est-ce que vous obtenez lorsque vous faites 'printf ("% 0.6f \ n ", floatingPart);'? –

+0

Pour développer le commentaire de @ MadPhysicist, la conversion d'un nombre à virgule flottante en nombre entier est tronquée vers zéro. –

Répondre

2

Le float le plus proche de 1.400000 est légèrement inférieur à 1.4. Vous pouvez vérifier que en faisant

printf("%0.8hf\n", floatingPart); 

Le résultat de ideone est 1.39999998. Cela signifie que 10 fois le premier chiffre après la virgule est 3.

Pour éviter ce problème, utilisez l'arrondi au lieu de la troncature. Un moyen facile d'arrondir est en ajoutant la moitié avant troncature:

printf("%d", (int)(numberForFactorial + 0.5f)); 

imprimera 4 que vous attendiez. Vous pouvez également utiliser round, rint, lround ou modf pour obtenir le même résultat: https://www.gnu.org/software/libc/manual/html_node/Rounding-Functions.html. L'arrondi est un sujet complexe, alors choisissez la méthode dont les contraintes correspondent le mieux à votre situation.

+0

oh f ** k .. maintenant je vois pourquoi ... – Nikitas

+0

@Nikitas. N'hésitez pas à sélectionner cette réponse si elle vous a expliqué ce qu'il fallait expliquer. –

+0

Et oui, les flotteurs sont une douleur dans le a **. –

2

Ceci est dû à la représentation binaire des valeurs à virgule flottante. Plus précisément, le 0.4 ou 2/5 ne peut pas être exprimé avec mantisse comme somme d'une combinaison comme 1/2 + 1/4 + 1/8 + ...

Le 1.400000 littéral est stocké comme quelque chose de plus proche de 1.399999976158142 dans son binaire représentation. La conversion en int tronque une partie non entière, donnant trois comme résultat final. Pour être pédant, le standard C ne nécessite pas de représentation binaire du type de données en virgule flottante, mais IEEE 754 est de facto le standard dans l'informatique d'aujourd'hui.

+1

J'espère que cela ne vous dérange pas mon édition. +1 –

+0

Hm ... oui je connais la chose 1/2 + 1/4 + 1/8 quand j'ai étudié "Les systèmes informatiques, une perspective de programmeur" troisième édition, chapitre 2, page 110 – Nikitas