Quiero eliminar dígitos de un flotante para tener un número fijo de dígitos después del punto, como:
1.923328437452 -> 1.923
Necesito enviar como una cadena a otra función, no imprimir.
También quiero ignorar los dígitos perdidos, no redondearlos.
python
floating-point
Joan Venge
fuente
fuente
Respuestas:
Primero, la función, para aquellos que solo quieren un código de copiar y pegar:
Esto es válido en Python 2.7 y 3.1+. Para las versiones anteriores, no es posible obtener el mismo efecto de "redondeo inteligente" (al menos, no sin mucho código complicado), pero el redondeo a 12 lugares decimales antes del truncamiento funcionará la mayor parte del tiempo:
Explicación
El núcleo del método subyacente es convertir el valor en una cadena con total precisión y luego simplemente cortar todo más allá del número deseado de caracteres. El último paso es sencillo; se puede hacer con manipulación de cuerdas
o el
decimal
moduloEl primer paso, convertir a una cadena, es bastante difícil porque hay algunos pares de literales de punto flotante (es decir, lo que escribe en el código fuente) que producen la misma representación binaria y, sin embargo, deben truncarse de manera diferente. Por ejemplo, considere 0.3 y 0.29999999999999998. Si escribe
0.3
en un programa Python, el compilador lo codifica utilizando el formato de punto flotante IEEE en la secuencia de bits (asumiendo un flotante de 64 bits)Este es el valor más cercano a 0.3 que se puede representar con precisión como un flotante IEEE. Pero si escribe
0.29999999999999998
en un programa de Python, el compilador lo traduce exactamente al mismo valor . En un caso, quería que se truncara (a un dígito) como0.3
, mientras que en el otro caso, quería que se truncase como0.2
, pero Python solo puede dar una respuesta. Esta es una limitación fundamental de Python, o de cualquier lenguaje de programación sin evaluación perezosa. La función de truncamiento solo tiene acceso al valor binario almacenado en la memoria de la computadora, no a la cadena que realmente ingresó en el código fuente. 1Si decodifica la secuencia de bits en un número decimal, nuevamente usando el formato de punto flotante IEEE de 64 bits, obtiene
por lo que se produciría una implementación ingenua
0.2
, aunque probablemente eso no sea lo que desea. Para obtener más información sobre el error de representación de punto flotante, consulte el tutorial de Python .Es muy raro trabajar con un valor de punto flotante que está tan cerca de un número redondo y, sin embargo, no es intencionalmente igual a ese número redondo. Entonces, al truncar, probablemente tenga sentido elegir la representación decimal "más bonita" de todas las que podrían corresponder al valor en la memoria. Python 2.7 y versiones posteriores (pero no 3.0) incluye un algoritmo sofisticado para hacer precisamente eso , al que podemos acceder a través de la operación de formato de cadena predeterminada.
La única advertencia es que esto actúa como una
g
especificación de formato, en el sentido de que usa notación exponencial (1.23e+4
) si el número es lo suficientemente grande o pequeño. Entonces, el método tiene que detectar este caso y manejarlo de manera diferente. Hay algunos casos en los que el uso de unaf
especificación de formato causa un problema, como intentar truncar3e-10
a 28 dígitos de precisión (produce0.0000000002999999999999999980
), y todavía no estoy seguro de cuál es la mejor manera de manejarlos.Si realmente está trabajando con
float
s que están muy cerca de los números redondeados pero intencionalmente no son iguales a ellos (como 0.29999999999999998 o 99.959999999999994), esto producirá algunos falsos positivos, es decir, redondeará los números que no desea redondear. En ese caso, la solución es especificar una precisión fija.El número de dígitos de precisión a usar aquí realmente no importa, solo necesita ser lo suficientemente grande para garantizar que cualquier redondeo realizado en la conversión de cadena no "aumente" el valor a su agradable representación decimal. Creo que
sys.float_info.dig + n + 2
puede ser suficiente en todos los casos, pero si no es así,2
podría ser necesario aumentarlo, y no está de más hacerlo.En versiones anteriores de Python (hasta 2.6 o 3.0), el formato de número de punto flotante era mucho más burdo y producía regularmente cosas como
Si ésta es su situación, si usted no desea utilizar "buenos" representaciones decimales para truncar, todo lo que puede hacer (por lo que yo sé) es elegir un número de dígitos, menos de lo representable precisión completa por una
float
, y alrededor de la número a esa cantidad de dígitos antes de truncarlo. Una elección típica es 12,pero puedes ajustar esto para que se adapte a los números que estás usando.
1 Bueno ... mentí. Técnicamente, puede indicarle a Python que vuelva a analizar su propio código fuente y extraiga la parte correspondiente al primer argumento que pase a la función de truncamiento. Si ese argumento es un literal de punto flotante, puede cortarlo un cierto número de lugares después del punto decimal y devolverlo. Sin embargo, esta estrategia no funciona si el argumento es una variable, lo que la hace bastante inútil. Lo siguiente se presenta solo con fines de entretenimiento:
Generalizar esto para manejar el caso en el que pasa una variable parece una causa perdida, ya que tendría que rastrear hacia atrás a través de la ejecución del programa hasta encontrar el literal de punto flotante que le dio a la variable su valor. Si es que hay uno. La mayoría de las variables se inicializarán a partir de la entrada del usuario o expresiones matemáticas, en cuyo caso la representación binaria es todo lo que hay.
fuente
applymap()
). Tal vez haya una manera de hacer que toda la operación sea más eficiente, pero ese sería un tema para una pregunta separada.Consulte la documentación de Python sobre los tipos estándar . Deberá desplazarse un poco hacia abajo para llegar a la función de ronda. Básicamente, el segundo número dice a cuántos lugares decimales redondearlo.
fuente
El resultado de
round
es un flotador, así que ten cuidado (el ejemplo es de Python 2.6):Estará mejor cuando utilice una cadena formateada:
fuente
round(1.23456, 3)
es1.235
y no1.2350000000000001
fuente
2
, tendrá un punto decimal.
al final de la cadena; no creo que sea una buena solución.En mi indicador de Python 2.7:
>>> int(1.923328437452 * 1000)/1000.0 1.923
fuente
Secuencia de comandos de Python simple -
fuente
Esto debería funcionar. Debería darle el truncamiento que está buscando.
fuente
La forma verdaderamente pitónica de hacerlo es
o más corto:
Actualizar
Por lo general, el problema no está en truncar los flotantes en sí, sino en el uso inadecuado de los números flotantes antes del redondeo.
Por ejemplo:
int(0.7*3*100)/100 == 2.09
.Si se ve obligado a usar flotadores (digamos, está acelerando su código con
numba
), es mejor usar centavos como "representación interna" de los precios: (70*3 == 210
) y multiplicar / dividir las entradas / salidas.fuente
int(0.7*3*100)/100 == 2.09
. ¿A dónde se fue mi 1 centavo?ImportError: cannot import name 'D'
, creo que querías hacer una importación con nombre, ¿no?Muchas de las respuestas dadas a esta pregunta son completamente incorrectas. O redondean flotantes (en lugar de truncar) o no funcionan para todos los casos.
Este es el principal resultado de Google cuando busco 'Python truncate float', un concepto que es realmente sencillo y que merece mejores respuestas. Estoy de acuerdo con Hatchkins en que usar el
decimal
módulo es la forma pitónica de hacer esto, así que doy aquí una función que creo que responde a la pregunta correctamente y que funciona como se esperaba para todos los casos.Como nota al margen, los valores fraccionarios, en general, no se pueden representar exactamente mediante variables binarias de punto flotante (consulte aquí para una discusión sobre esto), razón por la cual mi función devuelve una cadena.
fuente
Hice algo como esto:
fuente
Tu puedes hacer:
pruebas:
fuente
Si te apetece algo de matemática, esto funciona para + ve números:
fuente
Cuando uso un pandas df esto funcionó para mí
fuente
Solo quería mencionar que el viejo truco "hacer redondeo () con piso ()" de
se puede dar la vuelta para hacer piso () de redondo ()
Aunque estas dos reglas rompen con números negativos, usarlas es menos que ideal:
fuente
int (16,5); esto dará un valor entero de 16, es decir, trunc, no podrá especificar decimales, pero supongo que puede hacerlo por
fuente
He aquí una forma sencilla:
para num = 1.923328437452, esto da como resultado 1.923
fuente
fuente
Una función general y simple de usar:
fuente
Hay una solución fácil en Python 3. Dónde cortar Definí con una variable de ayuda decPlace para facilitar la adaptación.
Salida:
Espero eso ayude.
fuente
fuente
Variante corta y fácil
fuente
La mayoría de las respuestas son demasiado complicadas en mi opinión, ¿qué tal esto?
Simplemente escaneando el índice de '.' y truncar como se desee (sin redondeo). Convierta la cuerda en flotante como paso final.
O en su caso, si obtiene un float como entrada y desea una cadena como salida:
fuente
# dividir y multiplicar por 10 ** número de dígitos deseados
fuente
use numpy.round
fuente
Algo lo suficientemente simple como para caber en una lista de comprensión, sin bibliotecas u otras dependencias externas. Para Python> = 3.6, es muy sencillo escribir con f-strings.
La idea es dejar que la conversión de cadenas realice el redondeo a un lugar más de lo necesario y luego cortar el último dígito.
Por supuesto, aquí se está produciendo un redondeo (es decir, para el cuarto dígito), pero el redondeo en algún momento es inevitable. En caso de que la transición entre el truncamiento y el redondeo sea relevante, aquí hay un ejemplo un poco mejor:
Bono: eliminar ceros a la derecha
fuente
La idea central que se ofrece aquí me parece el mejor enfoque para este problema. Desafortunadamente, ha recibido menos votos mientras que la respuesta posterior que tiene más votos no está completa (como se observa en los comentarios). Con suerte, la siguiente implementación proporciona una solución corta y completa para el truncamiento .
que debería ocuparse de todos los casos de esquina que se encuentran aquí y aquí .
fuente
También soy un novato en Python y después de hacer uso de algunas piezas aquí, ofrezco mis dos centavos
str (int (time.time ())) tomará el tiempo epoch como int y lo convertirá en una cadena y se unirá con ... str (datetime.now (). microsecond) [: 3] que devuelve solo los microsegundos, convert para encadenar y truncar a los primeros 3 caracteres
fuente
fuente
Si se refiere a imprimir, lo siguiente debería funcionar:
fuente