2010-10-19 12 views
12

Tengo un problema de redondeo dentro de .Net.. Redondeo .Net Problema

Estoy redondeando un número de 3 dígitos a dos dígitos y está causando algunos problemas con un número.

Si trato de redondear 34.425 a dos decimales, debería redondearlo a 34.43. Estoy usando la opción roundawayfromzero y ha funcionado para todos los números del programa, excepto para este hasta ahora.

El código Math.Round(34.425, 2, MidpointRounding.AwayFromZero) debe ser igual a 34.43, sin embargo, es igual a 34.42.

Si pruebo esto con cualquier otro número, funciona bien.

Math.Round(34.435, 2, MidpointRounding.AwayFromZero) = 34.44 

Math.Round(34.225, 2, MidpointRounding.AwayFromZero) = 34.23 

Math.Round(34.465, 2, MidpointRounding.AwayFromZero) = 34.47 

Solo quería comprobar si alguien ha tenido este problema antes?

Por ahora, he resuelto este problema convirtiendo el número a un decimal. He cambiado el código para esto y funciona bien ahora:

Math.Round(CDec(34.425), 2, MidpointRounding.AwayFromZero) = 34.43 

estoy buscando por una razón de por qué mi viejo código no funcionaba.

¡Gracias!

Actualizado el código hasta el punto AwayFromZero

Respuesta

20

flotante correcta nunca es exacta, 34.425 pueden tener un represantation interna 34,4249999999999 .. que se redondea a 34.42.

Si necesita una representación exacta de los números, utilice el tipo decimal.

+1

+1 para sugerencia decimal –

+0

Gracias por la respuesta. Supongo que mi gran pregunta es: ¿por qué funciona esto para todos los demás valores? – Jeff

+0

También tendría que estar de acuerdo contigo si fuera una variable. Sin embargo, estaba poniendo este valor en la lista de vigilancia como 34.425. Entonces no debería estar representado como 34.43499999 ... ¿Es correcto en mi suposición? – Jeff

2

Un poco confundido acerca de si realmente está usando MidpointRounding.ToEven o MidpointRounding.AwayFromZero. Si está utilizando ToEven como indica el primer fragmento, este es el comportamiento esperado.

+0

Edité la pregunta, perdón por la confusión. – Jeff

1

Sus supuestos y los resultados son incorrectos:

Math.Round(34.225, 2, MidpointRounding.ToEven) == 34.22 
Math.Round(34.465, 2, MidpointRounding.ToEven) == 34.46 

y

Math.Round(34.425, 2, MidpointRounding.ToEven) == 34.42 

Eso es como funciona, y eso es lo que me pasa en mi caja. Redondear a par significa exactamente eso, redondeando hacia arriba o hacia abajo para llegar al siguiente número par en el lugar decimal de interés.

+0

Lo siento, copié el código incorrecto. Todos ellos deben ser AwayFromZero. – Jeff

+0

Esto solo se aplica si el siguiente decimal después del lugar decimal de interés es 5, y todos los decimales posteriores son cero. – phoog

1

El código Math.Round (34.425, 2, MidpointRounding.ToEven) debe ser igual a 34.43, sin embargo, es igual a 34.42.

¿Por qué? ToEven debe hacerlo 34.42 ya que 42 es par. El comportamiento es correcto.

0

No uso vb.net, entonces mi razonamiento puede ser incorrecto, pero basado en los nombres de sus parámetros MidpointRounding.ToEven, esperaría que 34.425 se redondee a 34.42; pero también esperaría que 34.225 se redondee a 34.22 y 34.465 a 34.46. El redondeo de números que termina en 5 como en sus ejemplos es una cuestión de convención. La convención más habitual es redonda a un número par, lo que deduzco que su parámetro .ToIn estaría adoptando.

Además, sospecho que se encuentra con el problema de redondeo binario/decimal. Verificando la representación binaria de 34.425 sale como 10010.011011 ....... Cuando toma en cuenta el almacenamiento de la computadora y la representación de un número decimal (byte, palabra, palabra doble, palabra cuádruple y complemento negativo/positivo), esto puede dar como resultado en ti no redondeas el número que creías que eras

Para obtener los resultados que desea, probablemente debería agregar 0.00001 a cualquier dígito que termine en 5 antes del redondeo.