2009-05-25 6 views
10

Considérez ceci:Pourquoi l'opérateur de module ne fonctionne-t-il pas en double dans C#?

double x,y; 
x =120.0; 
y = 0.05; 

double z= x % y; 

J'ai essayé et attendu que le résultat soit 0, mais il est sorti 0,04933333.

Cependant,

x =120.0; 
y = 0.5; 
double z= x % y; 

ne fait donné le résultat correct de 0.

Qu'est-ce qui se passe ici?

J'ai essayé Math.IEEERemainder(double, double) mais il ne renvoie pas 0 non plus. Qu'est-ce qui se passe ici?

Aussi, en aparté, quelle est la manière la plus appropriée de trouver le reste en C#?

+0

Il serait intéressant de savoir ce que vous essayez d'atteindre. Utiliser un module avec des nombres à virgule flottante n'est jamais une bonne idée car les réponses indiquent déjà. – VVS

Répondre

14

En raison de son format de stockage, double s ne peut pas stocker toutes les valeurs exactement telles qu'elles sont entrées ou affichées. La représentation humaine des nombres est généralement au format décimal, alors que double s sont basés sur le système dual.

Dans un double, 120 est stocké précisément parce que c'est une valeur entière. Mais 0.05 ne l'est pas. Le double est approché du nombre le plus proche de 0.05 qu'il peut représenter. 0.5 est une puissance de 2 (1/2), donc il peut être stocké avec précision et vous n'obtenez pas une erreur d'arrondi.

Pour avoir tous les nombres exactement de la même manière que vous les entrez/affichez dans le système décimal, utilisez plutôt decimal.

decimal x, y; 
x = 120.0M; 
y = 0.05M; 

decimal z = x % y; // z is 0 
+0

Un 'double 'est toujours une valeur exacte. L'opération qui a déterminé sa valeur peut être inexacte. 'double a = 0.1;' -> 'a' a une valeur exacte qui peut différer légèrement de 0.1 mathématique. 'b double = 0,125;' -> 'b' a une valeur exacte qui est la même que mathématique 0,125. Toujours bonne idée d'utiliser 'decimal'. – chux

+2

"valeur exacte pouvant différer légèrement" == inexact. –

+0

Avec des entiers, le quotient de 7 divisé par 3 est 2 et diffère du quotient mathématique de 2.333 .... cependant les entiers sont considérés comme exacts. De même, avec FP, 7,0 divisé par 3,0 donne une réponse proche, mais pas la même, que la valeur de la mathématique 2.333 ... Dans les deux cas, les opérations ne sont pas exactement les mêmes que les mathématiques. Dans les deux cas, les résultats sont exacts. – chux

9

Vous pouvez faire quelque chose comme:

double a, b, r; 

a = 120; 
b = .05; 

r = a - Math.floor(a/b) * b; 

Cela devrait aider;)

0

Modulus devrait seulement être utilisé avec entier. Le reste provient d'une division euclidienne. Avec le double, vous pouvez avoir des résultats inattendus.

Voir this article

+2

vous pouvez utiliser sans risque le module avec des décimales. –

1

Je crois que si vous avez essayé la même chose avec decimal il fonctionnerait correctement.

Questions connexes