Pregunta

No veo el resultado que espero con Math.Round.

return Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97

Según entiendo MidpointRounding.ToEven, el 5 en la posición de las milésimas debería hacer que la salida sea 99.96. ¿No es este el caso?

Incluso intenté esto, pero también devolvió 99.97:

return Math.Round(99.96535789 * 100, MidpointRounding.ToEven)/100;

¿Qué me estoy perdiendo?

¡Gracias!

¿Fue útil?

Solución

No estás realmente en el punto medio. MidpointRounding.ToEven indica que si tuviera el número 99.965 , es decir, 99.96500000 [etc.], entonces obtendría 99.96. Dado que el número que está pasando a Math.Round está por encima de este punto medio, se está redondeando.

Si desea que su número se redondee a 99.96, haga lo siguiente:

// this will round 99.965 down to 99.96
return Math.Round(Math.Truncate(99.96535789*1000)/1000, 2, MidpointRounding.ToEven);

Y oye, aquí hay una pequeña y útil función para hacer lo anterior para casos generales:

// This is meant to be cute;
// I take no responsibility for floating-point errors.
double TruncateThenRound(double value, int digits, MidpointRounding mode) {
    double multiplier = Math.Pow(10.0, digits + 1);
    double truncated = Math.Truncate(value * multiplier) / multiplier;
    return Math.Round(truncated, digits, mode);
}

Otros consejos

Solo se redondea a 99.96 si está en el punto medio, es decir, 99.965:

C:\temp>ipy
IronPython 2.6 Beta 2 (2.6.0.20) on .NET 2.0.50727.4927
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr
>>> from System import Math, MidpointRounding
>>> Math.Round(99.9651, 2, MidpointRounding.ToEven)
99.97
>>> Math.Round(99.965, 2, MidpointRounding.ToEven)
99.96
>>> Math.Round(99.9649, 2, MidpointRounding.ToEven)
99.96
>>> Math.Round(99.975, 2, MidpointRounding.ToEven)
99.98
>>>

El valor MidpointRounding solo entra en juego cuando intentas redondear un valor cuyo dígito menos significativo es exactamente 5. En otras palabras, el valor tendría que ser 99.965 para obtener el resultado deseado. Como este no es el caso aquí, simplemente está observando el mecanismo de redondeo estándar. Consulte la página MSDN para obtener más información.

Aquí están los resultados que arrojan algo de luz sobre el tema:

Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97
Math.Round(99.965, 2, MidpointRounding.ToEven);      // returning 99.96
Math.Round(99.96500000, 2, MidpointRounding.ToEven); // returning 99.96

El punto medio es exactamente 5 ... no 535789, no 499999.

El redondeo del punto medio se mira solo si el valor está entre sus dos casos.

En su caso, no es '' 5 '', es '' 535 ... '', por lo que es mayor que el punto medio y las rutinas a .96. Para obtener el comportamiento que esperaba, necesitaría truncar hasta el tercer punto decimal, ENTONCES redondear utilizando MidpointRounding.ToEven.

Math.Round 'Redondea un valor decimal a un número específico de dígitos fraccionarios.' al redondear 99.96500000,2 se redondea a 99.96 y 99.96500001 a 99.67. Redondea el valor completo.

Si fuera yo, no usaría Math.Round () , porque eso no es lo que está tratando de lograr.

Esto es lo que haría:

double num = 99.96535789;
double percentage = Math.Floor(100 * num) / 100;  

Que es mucho más fácil de leer y es más un enfoque matemático.
Multiplico el número por 100 , ahora tengo 9996.535789 .
Luego, al piso, que es distintivamente diferente al redondeo, para devolver el número entero más pequeño más cercano al número, para obtener 9996 .
Luego divido por 100 para obtener el 99.96 requerido.

P.S.
Floor es lo opuesto a ceiling , que devuelve el número entero más grande más cercano al número.
Entonces, el límite de 9996.535789 es 9997 .
Ambos son diferentes a redondear sin puntos decimales, lo que en realidad devuelve el número entero más cercano al número, ya sea más pequeño o más grande, lo que sea más cercano; Es por eso que estaba obteniendo 99.97 cuando usaba redondeo .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top