round redondear mas entero decimales c# decimal rounding int32

c# - redondear - ¿Por qué Convert.ToInt32() se redondea al número par más cercano, en lugar del número entero más cercano?



redondear a entero c# (4)

Esta es exactamente la razón por la cual la sobrecarga MidpontRounding se agregó a Math.Round .

Por lo tanto, para el redondeo correcto, debe usar Math.Round en lugar de Convert.ToInt32.

Mirando la documentación de Convert.ToInt32() para Convert.ToInt32() dice:

Si el valor está a medio camino entre dos números enteros, se devuelve el número par; es decir, 4.5 se convierte a 4 y 5.5 se convierte a 6.

http://msdn.microsoft.com/en-us/library/ffdk7eyz.aspx

¿Por qué es esto?

Seguramente sería más lógico redondear al número entero más cercano, ¿no es así? Si es así, 4.5 se convertiría en 5, y 5.5 se convertiría en 6, lo que parece ser más intuitivo.


Si desea ese comportamiento, debe usar Math.Round y especificar MidpointRounding.AwayFromZero .

Por ejemplo:

int result = (int)Math.Round(4.5, MidpointRounding.AwayFromZero);

Demostración: http://ideone.com/ZAbBL

http://msdn.microsoft.com/en-us/library/ffdk7eyz.aspx no usa Math.Round sí, en su lugar se implementa de esta manera (ILSpy):

public static int ToInt32(double value) { if (value >= 0.0) { if (value < 2147483647.5) { int num = (int)value; double num2 = value - (double)num; if (num2 > 0.5 || (num2 == 0.5 && (num & 1) != 0)) { num++; } return num; } } else { if (value >= -2147483648.5) { int num3 = (int)value; double num4 = value - (double)num3; if (num4 < -0.5 || (num4 == -0.5 && (num3 & 1) != 0)) { num3--; } return num3; } } throw new OverflowException(Environment.GetResourceString("Overflow_Int32")); }


Sin tener en cuenta la pregunta subjetiva de si MidpointRounding.ToEven (redondeo bancario) o MidpointRounding.AwayFromZero sería un mejor valor predeterminado.

Al diseñar esto, Microsoft habría considerado los idiomas .NET fue diseñado para reemplazar.

  • VB classic siempre ha usado Banker''s Rounding por defecto.

  • Las conversiones de C / C ++ se truncan al emitir, y tiene las funciones de biblioteca floor () y ceil () en la biblioteca de tiempo de ejecución, pero (AFAIK, puede ser incorrecto) no tiene función de redondeo.

  • Java tiene un Math.round que en la documentación se describe como equivalente a Math.round (a + 0.5). Lo que podría decirse que no es lo que la mayoría de la gente esperaría para los números negativos (-3.5 se redondea a -3).

  • Se podría decir que los desarrolladores de VB necesitarán más apoyo que los desarrolladores procedentes de C / C ++ o Java.

Por lo tanto, parece razonable que al diseñar .NET, la biblioteca de clases proporcione los métodos de Floor , Ceiling y Round , y que el comportamiento de la Ronda se corresponda con el comportamiento de VB.

También parece razonable que Convert.ToInt32 () use el método Round (aunque creo que se podría hacer un caso para Floor, para mantener la coherencia con el casting).


La sección de Historia de la entrada de Wikipedia para Rounding tiene algunas afirmaciones sobre el papel de "redondeo para igualar" en computación. Curiosamente, parece que "Bankers Rounding" tiene poca evidencia para afirmar que fue oficial en cualquier sentido de la palabra, por lo que solo puede ser considerado como terminología de argot.

Solo es "más lógico" si se suscribe a ese mecanismo de redondeo. El redondeo de los banqueros (que es el predeterminado en este caso) también es perfectamente lógico.

Imagínese si los bancos redondearan al centavo más cercano por cada cantidad fraccionaria, harían mucho menos dinero (perderían mucho, para el cínico) con los millones y millones de transacciones que se procesan diariamente. OK, entonces este ejemplo es cínico.

Ir hacia el número par más cercano (o impar, pero la historia eligió lo contrario) significa que no todas las resoluciones de redondeo aumentan , algunas pueden disminuir . Cuando pone esto a la ley de promedios, se convierte en una solución justa para usar cuando se considera quién es responsable de pagar el medio centavo adicional.

En cuanto a por qué se eligió esto para el marco, esta pregunta intenta abordarlo:

¿Por qué .NET usa el redondeo bancario por defecto?

Por supuesto, todo esto se remonta a los días financieros y su aplicabilidad a los números integrales podría cuestionarse, pero ¿por qué molestarse? Acéptalo, anulalo si quieres, solo entiende cómo funciona.

Para las personas que se preguntan cómo cambiar el redondeo predeterminado:

Si está proporcionando un número no entero a Convert.ToInt32 , primero deberá hacer algo como Convert.ToDouble y luego Math.Round con la sobrecarga para cambiar la lógica de redondeo .