.net - sirve - reglas de redondeo fisica
¿Por qué.NET usa el redondeo bancario por defecto? (5)
Según la documentación, el método decimal.Round
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 de redondeo más natural:
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 de marco?
¿Hay alguna implementación incorporada del algoritmo de redondeo a mitad de camino 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)
como resultado, pero obtiene 2 en su lugar.
Las otras respuestas con razones por las que el algoritmo de Banker (también conocido como la mitad redonda es una buena opción) son bastante correctas. No sufre sesgos negativos o positivos tanto como la mitad redonda lejos del método cero en la mayoría de las distribuciones 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 enumeración MidpointRounding
. Por supuesto, podrían haber brindado más alternativas para resolver los vínculos, pero eligen simplemente cumplir con el estándar IEEE.
Los decimales se utilizan principalmente para el dinero ; El redondeo bancario es común cuando se trabaja con dinero . O se podría decir.
En su mayoría son los banqueros que necesitan el tipo decimal; por lo tanto hace "redondeo bancario"
El redondeo de los banqueros tiene la ventaja de que, en promedio, obtendrá el mismo resultado si:
- redondear un conjunto de "líneas de factura" antes de sumarlas,
- o sumarlos luego redondear el total
Redondear antes de sumar ahorró mucho trabajo en los días anteriores a las computadoras.
(En el Reino Unido, cuando los bancos decimales no se ocupaban de la mitad de los peniques, pero durante muchos años todavía existía una moneda de media penique y la tienda a menudo tenía precios que terminaban en la mitad de los peniques, por lo que muchos redondeos)
Probablemente porque es un algoritmo mejor. En el transcurso de muchos redondeos realizados, promediará que todos los .5 terminan redondeando igualmente hacia arriba y hacia abajo. Esto proporciona mejores estimaciones de los resultados reales si, por ejemplo, está agregando un montón de números redondeados. Yo diría que aunque no es lo que algunos pueden esperar, probablemente sea lo más correcto.
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
te permite especificar un MidpointRounding
:
- ToEven: cuando un número está a medio camino entre otros dos, se redondea hacia el número par más cercano.
- AwayFromZero: cuando un número está a medio camino entre otros dos, se redondea hacia el número más cercano que está lejos de cero.
Usa otra sobrecarga de la función Round como esta:
decimal.Round(2.5m, 0,MidpointRounding.AwayFromZero)
Saldrá 3 . Y si usas
decimal.Round(2.5m, 0,MidpointRounding.ToEven)
obtendrá redondeo de banquero.