math - signo - ¿Por qué los lenguajes de programación redondean hasta.6?
redondear valores python (7)
¿Puedes dar algún código de ejemplo, porque ese no es el comportamiento que veo en Python?
>>> "%.1f" % 1.54
''1.5''
>>> "%.1f" % 1.55
''1.6''
>>> "%.1f" % 1.56
''1.6''
Si coloca un decimal en un formato donde debe redondearse al décimo más cercano, y es: 1.55, redondeará a 1.5. 1.56 luego redondeará a 1.6. En la escuela, recuerdo haber aprendido que completas cuando alcanzas cinco, y bajas si es 4 o menos. ¿Por qué es diferente en Python, et al.
Aquí hay un ejemplo de código para Python 2.6x (cualquiera que sea la última versión)
''{0:01.2f}''.format(5.555) # This will return ''5.55''
Después de probar algunos de los ejemplos proporcionados, me di cuenta de algo aún más confuso:
''{0:01.1f}''.format(5.55) # This will return ''5.5''
# But then
''{0:01.1f}''.format(1.55) # This will return ''1.6''
Por qué la diferencia al usar 1.55 vs 5.55. Ambos se escriben como literales (por lo que flotan)
En primer lugar, en la mayoría de los lenguajes una constante no decorada como "1.55" se trata como un valor de doble precisión. Sin embargo, 1.55 no es exactamente representable como valor de doble precisión, porque no tiene una representación de terminación en binario. Esto causa muchos comportamientos curiosos, pero un efecto es que cuando escribe 1.55, en realidad no obtiene el valor exactamente a la mitad entre 1.5 y 1.6.
En binario, el número decimal 1.55 es:
1.10001100110011001100110011001100110011001100110011001100110011001100...
Cuando escribe "1.55", este valor en realidad se redondea al valor de precisión doble representable más cercano (en muchos sistemas ... pero hay excepciones, a las que llegaré). Este valor es:
1.1000110011001100110011001100110011001100110011001101
que es ligeramente más grande que 1.55; en decimal, es exactamente:
1.5500000000000000444089209850062616169452667236328125
Por lo tanto, cuando se le solicite redondear este valor a un solo dígito después de la posición decimal, redondeará hasta 1.6. Esta es la razón por la cual la mayoría de los comentaristas han dicho que no pueden duplicar el comportamiento que está viendo.
Pero espere, en su sistema, "1.55" redondeado hacia abajo , no hacia arriba. ¿Que esta pasando?
Podrían ser algunas cosas diferentes, pero lo más probable es que esté en una plataforma (probablemente Windows), que de forma predeterminada realiza aritmética de punto flotante utilizando instrucciones x87, que utilizan un formato interno diferente (80 bits). En el formato de 80 bits, 1.55 tiene el valor:
1.100011001100110011001100110011001100110011001100110011001100110
que es ligeramente más pequeño que 1.55; en decimal, este número es:
1.54999999999999999995663191310057982263970188796520233154296875
Debido a que es apenas más pequeño que 1.55, redondea hacia abajo cuando se redondea a un dígito después del punto decimal, dando el resultado "1.5" que está observando.
FWIW: en la mayoría de los lenguajes de programación, el modo de redondeo predeterminado es en realidad "redondeado al más cercano, vinculado con par". Es solo que cuando especifica valores fraccionarios en decimales, casi nunca toca un caso exacto a la mitad, por lo que puede ser difícil para un lego observar esto. Puede verlo, sin embargo, si observa cómo "1.5" se redondea a cero dígitos:
>>> "%.0f" % 0.5
''0''
>>> "%.0f" % 1.5
''2''
Tenga en cuenta que ambos valores se redondean a números pares ; ninguno redondea a "1".
Editar: en su pregunta revisada, parece haber cambiado a un intérprete de Python diferente, en el que el punto flotante se realiza en el tipo doble IEEE754, no en el tipo x87 de 80 bits. Por lo tanto, "1.55" redondea, como en mi primer ejemplo, pero "5.55" se convierte en el siguiente valor binario de coma flotante:
101.10001100110011001100110011001100110011001100110011
que es exactamente:
5.54999999999999982236431605997495353221893310546875
en decimal ya que es menor que 5.55, redondea hacia abajo .
Esto no parece ser el caso. Estás usando el formateador de cuerdas "flotante", ¿verdad?
>>> "%0.2f" % 1.55
''1.55''
>>> "%0.1f" % 1.55
''1.6''
>>> "%0.0f" % 1.55
''2''
Hay muchas formas de redondear números. Puede leer más sobre el redondeo en Wikipedia . El método de redondeo utilizado en Python es la mitad de cero y el método de redondeo que está describiendo es más o menos el mismo (al menos para números positivos).
No puedo ver una razón para el comportamiento exacto que estás describiendo. Si sus números son solo ejemplos, un escenario similar puede explicarse por el uso de redondeo bancario:
1.5 rounds to 2
2.5 rounds to 2
3.5 rounds to 4
4.5 rounds to 4
Es decir, un valor .5 se redondeará al número entero par más cercano. La razón de esto es que redondear una gran cantidad de números se nivelaría a largo plazo. Si un banco, por ejemplo, va a pagar inquietud a un millón de clientes, y el 10% de ellos termina con un valor de .5 centavos para ser redondeado, el banco pagaría $ 500 más si los valores se redondearan en su lugar.
Otra razón para el redondeo inesperado es la precisión de los números de coma flotante. La mayoría de los números no se pueden representar exactamente, por lo que están representados por la aproximación más cercana posible. Cuando piensas que tienes un número que es 1.55, en realidad puedes terminar con un número como 1.54999. Redondear ese número a un decimal, por supuesto, daría como resultado 1.5 en lugar de 1.6.
Redondeo y truncamiento es diferente para cada lenguaje de programación, por lo que su pregunta probablemente esté relacionada directamente con Python.
Sin embargo, el redondeo como práctica depende de su metodología.
También debe saber que CONVERTIR un decimal a un número entero en muchos lenguajes de programación produce resultados diferentes de redondear realmente el número.
Editar: según algunos de los otros carteles, parece que Python no muestra el comportamiento de redondeo que describió:
>>> "%0.2f" % 1.55
''1.55''
>>> "%0.1f" % 1.55
''1.6''
>>> "%0.0f" % 1.55
''2''
Un método para eliminar al menos un aspecto de los problemas de redondeo (al menos algunas veces) es realizar un preprocesamiento. Los formatos de precisión simple y doble pueden representar todos los enteros exactamente de -2 ^ 24-1 a 2 ^ 24-1 y -2 ^ 53-1 a 2 ^ 53-1 respectivamente. Lo que se puede hacer con un número real (con una parte de fracción distinta de cero) es
- quítese el cartel y guárdelo para más tarde
- multiplique el número positivo restante con 10 ^ (número de decimales requerido)
- agregue 0.5 si el modo de redondeo de su entorno está configurado para cortar (ronda hacia cero)
- redondea el número al más cercano
- sprintf el número de una cadena con 0 decimales en formato
- formatee "manualmente" la cuerda según su longitud después del sprintf, el número de decimales requerido, el punto decimal y el signo
- la cadena ahora debe contener el número exacto
Tenga en cuenta que si el resultado después del paso 3 excede el rango del formato específico (arriba) su respuesta será incorrecta.