2009-05-25 12 views
10

Considera:¿Por qué el operador de módulo no funciona para el doble en C#?

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

double z= x % y; 

Probé esto y esperaba que el resultado sea 0, pero salió 0,04933333.

Sin embargo,

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

, efectivamente, dio el resultado correcto de 0.

¿Qué está pasando aquí?

Intenté Math.IEEERemainder(double, double) pero tampoco devuelve 0. ¿Que esta pasando aqui?

Además, aparte, ¿cuál es la forma más adecuada de encontrar el resto en C#?

+0

Sería interesante saber lo que está tratando de lograr. El uso de módulos con números de punto flotante nunca es una buena idea ya que las respuestas ya lo indican. – VVS

Respuesta

14

Debido a su formato de almacenamiento, double s no puede almacenar todos los valores exactamente como se ingresan o se muestran. La representación humana de los números suele ser en formato decimal, mientras que double s se basan en el sistema dual.

En un double, 120 se almacena precisamente porque es un valor entero. Pero 0.05 no lo es. El doble se aproxima al número más cercano a 0.05 que puede representar. 0.5 es una potencia de 2 (1/2), por lo que se puede almacenar con precisión y no se produce un error de redondeo.

Para tener todos los números exactamente de la misma manera que lo ingresa/muestra en el sistema decimal, use decimal en su lugar.

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

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

Un 'doble' es siempre un valor exacto. La operación que determinó su valor puede ser inexacta. 'double a = 0.1;' -> 'a' tiene un valor exacto que puede diferir ligeramente de la matemática 0.1. 'double b = 0.125;' -> 'b' tiene un valor exacto que es el mismo que 0.125 matemático. Todavía es una buena idea usar 'decimal'. – chux

+2

"valor exacto que puede diferir ligeramente" == inexacto. –

+0

Con números enteros, el cociente de 7 dividido por 3 es 2 y difiere del cociente matemático de 2.333 ... pero los enteros se consideran exactos. Del mismo modo con FP, 7.0 dividido por 3.0 resultados en una respuesta cercana, pero no es lo mismo que, el valor matemático de 2.333 ... En ambos casos, las operaciones no son exactamente las mismas que las matemáticas. En ambos casos, los resultados son exactos. – chux

9

Se podría hacer algo como:

double a, b, r; 

a = 120; 
b = .05; 

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

Esto debería ayudar;)

0

módulo debe solo se usará con entero. El resto proviene de una división euclidiana. Con doble, puede tener resultados inesperados.

Ver this article

+2

puede usar el módulo de forma segura con decimales. –

1

Creo que si se trató de la misma con decimal que funcionaría correctamente.

Cuestiones relacionadas