Según la documentación, el decimal.Round
método utiliza un algoritmo de redondeo a par que no es común para la mayoría de las aplicaciones. Así que siempre termino escribiendo una función personalizada para hacer el algoritmo más natural de redondeo a la mitad:
public static decimal RoundHalfUp(this decimal d, int decimals)
{
if (decimals < 0)
{
throw new ArgumentException("The decimals must be non-negative",
"decimals");
}
decimal multiplier = (decimal)Math.Pow(10, decimals);
decimal number = d * multiplier;
if (decimal.Truncate(number) < number)
{
number += 0.5m;
}
return decimal.Round(number) / multiplier;
}
¿Alguien sabe la razón detrás de esta decisión de diseño del marco?
¿Existe alguna implementación incorporada del algoritmo de redondeo a la mitad en el marco? ¿O tal vez alguna API de Windows no administrada?
Podría ser engañoso para los principiantes que simplemente escriben decimal.Round(2.5m, 0)
esperando 3 como resultado, pero obteniendo 2 en su lugar.
Respuestas:
Probablemente porque es un mejor algoritmo. En el transcurso de muchos redondeos realizados, promediarás que todos los .5 terminan redondeándose por igual hacia arriba y hacia abajo. Esto proporciona mejores estimaciones de los resultados reales si está, por ejemplo, agregando un montón de números redondeados. Diría que, aunque no es lo que algunos pueden esperar, probablemente sea lo más correcto.
fuente
Las otras respuestas con razones por las cuales el algoritmo de Banker (también conocido como la mitad redonda o incluso ) es una buena opción son bastante correctas. No sufre sesgos negativos o positivos tanto como la mitad redonda del método cero respecto de las distribuciones más razonables.
Pero la pregunta era por qué .NET usa el redondeo real de Banker como predeterminado, y la respuesta es que Microsoft ha seguido el estándar IEEE 754 . Esto también se menciona en MSDN para Math.Round en Comentarios.
También tenga en cuenta que .NET admite el método alternativo especificado por IEEE al proporcionar la
MidpointRounding
enumeración. Por supuesto, podrían haber proporcionado más alternativas para resolver los lazos, pero eligen cumplir con el estándar IEEE.fuente
Si bien no puedo responder a la pregunta "¿Por qué los diseñadores de Microsoft eligieron esto como predeterminado?", Solo quiero señalar que no es necesaria una función adicional.
Math.Round
le permite especificar unMidpointRounding
:fuente
Los decimales se usan principalmente por dinero ; El redondeo bancario es común cuando se trabaja con dinero . O podrías decirlo.
El redondeo de los banqueros tiene la ventaja de que, en promedio, obtendrá el mismo resultado si:
El redondeo antes de sumar ahorró mucho trabajo en los días anteriores a las computadoras.
(En el Reino Unido, cuando fuimos a los bancos decimales, no manejaban medio penique, pero durante muchos años todavía había una moneda de medio penique y la tienda a menudo tenía precios que terminaban en medio penique, así que muchos redondeos)
fuente
Decmial
s, si. Decimales, no. Para la posteridad, estoy de acuerdo con el sentimiento original aquí.Use otra sobrecarga de la función Round como esta:
Saldrá 3 . Y si usas
Obtendrá redondeo de banquero.
fuente