2 votes

précision du calcul du flotteur

J'ai rencontré un problème de précision de calcul des flottants en C#, voici l'exemple minimal de travail :

int num = 160;
float test = 1.3f;

float result = num * test;
int result_1 = (int)result;
int result_2 = (int)(num * test);
int result_3 = (int)(float)(num * test);

Console.WriteLine("{0} {1} {2} {3}", result, result_1, result_2, result_3);

Le code ci-dessus produira "208 208 207 208", quelqu'un pourrait-il expliquer la valeur bizarre de result_2 qui devrait être 208 ? (le binaire ne peut pas représenter 1.3 précisément, ce qui causerait un problème de précision des flottants, mais je suis curieux des détails).

3voto

Slaven Tojic Points 2500

num * test vous donnera probablement un résultat comme 207.9999998... et quand vous lancez cette float à la valeur int vous obtenez 207 car le casting à int arrondira le résultat au nombre entier le plus proche dans ce cas. 207 (similaire à Math.Floor() ).

Si vous attribuez num * test à un type de flotteur comme float result = num * test; la valeur 207.9999998... sera arrondi à la valeur flottante la plus proche qui est 208 .

Passons à l'été :

float result = num * test; vous donne 208 parce que vous assignez num * test à un type flottant.

int result_1 = (int)result; vous donne 208 parce que vous coulez la valeur de result à int -> (int)208 .

int result_2 = (int)(num * test); vous donne 207 parce que vous coulez quelque chose comme 207.9999998... vers int -> (int)207.9999998... .

int result_3 = (int)(float)(num * test); vous donne 208 parce que vous faites d'abord un casting de 207.9999998... vers float qui vous donne 208 et ensuite vous faites un casting de 208 vers int.

0voto

SeM Points 3833

Vous pouvez également jeter un coup d'œil à C# spécification du langage :

Les opérations en virgule flottante peuvent être effectuées avec une précision supérieure à celle du type de résultat de l'opération. Par exemple, certaines architectures matérielles prennent en charge un type de virgule flottante "étendu" ou "double long" avec une plage et une précision plus grandes que le type double, et exécutent implicitement toutes les opérations en virgule flottante en utilisant ce type de précision supérieure. Ce n'est qu'au prix d'un coût excessif en termes de performances que de telles architectures matérielles peuvent effectuer des opérations en virgule flottante avec une précision moindre. Plutôt que d'exiger d'une implémentation qu'elle renonce à la fois aux performances et à la précision, C# permet d'utiliser un type de précision supérieure pour toutes les opérations en virgule flottante. Outre le fait de fournir des résultats plus précis, cela a rarement des effets mesurables. Cependant, dans les expressions de la forme x * y / z, où la multiplication produit un résultat qui est en dehors de la plage double, mais où la division suivante ramène le résultat temporaire dans la plage double, le fait que l'expression soit évaluée dans un format de plage supérieure peut entraîner la production d'un résultat fini au lieu d'une infinité.

Donc, en gros, pour répondre à votre question - Non, ça ne devrait pas. . Vous pouvez utiliser différents types, à savoir decimal o Points flottants binaires etc. Et si vous êtes plus intéressé par les concepts et formats de virgule flottante, vous pouvez lire Jeffrey Sax - Floating Point in .NET part 1 : Concepts et formats .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X