HOWTO · Python
Cómo redondear un número a dígitos significativos en Python
Aprenda a redondear números de Python a dígitos significativos con round(), math, formateo, Decimal, sigfig y NumPy.
En esta página
Para redondear un número a una cantidad elegida de dígitos significativos, encuentre su magnitud decimal y pase el conteo de posiciones decimales correspondiente a round(). Por ejemplo, 1.342 redondeado a un dígito significativo se convierte en 1.000. La función integrada es suficiente para un solo valor; use una función auxiliar para cálculos repetidos, el formateo cuando el resultado debe permanecer como texto, Decimal cuando importan las reglas de redondeo decimal, o NumPy para matrices.
Redondear a dígitos significativos con round() de Python’s
round(number, ndigits) redondea a una cantidad de posiciones decimales. Para dígitos significativos, calcule ndigits como digits - 1 - floor(log10(abs(number))). Para 1.342 y un dígito significativo, esto es 1 - 1 - 3, o -3, por lo que Python redondea al millar más cercano.
Ejecute este ejemplo:
print(round(1342, -3))
1000
Python utiliza el redondeo al par (ties-to-even) para los casos a mitad de camino, de modo que el último dígito retenido es par cuando el valor está exactamente a mitad de camino entre dos valores redondeados. Esto es diferente de redondear siempre un empate alejándose de cero. Un ndigits negativo redondea a decenas, centenas o potencias de diez mayores. round() devuelve un número; no conserva los ceros finales como convención de presentación. En el caso de entradas de punto flotante, la aproximación binaria almacenada también puede afectar a los empates decimales aparentes.
Redondear a dígitos significativos con una función auxiliar de math
Una función auxiliar puede calcular el conteo de posiciones decimales a partir de la magnitud en base 10. La siguiente versión acepta conteos de dígitos enteros positivos y valores numéricos finitos, y devuelve cero sin cambios. Lanza ValueError para un conteo de dígitos no admitido o una entrada no finita, ya que log10() no puede determinar una magnitud decimal finita para esos valores.
from math import floor, isfinite, log10
def round_significant(value, digits):
if not isinstance(digits, int) or digits < 1:
raise ValueError("digits must be a positive integer")
if not isfinite(value):
raise ValueError("value must be finite")
if value == 0:
return value
places = digits - 1 - floor(log10(abs(value)))
return round(value, places)
print(round_significant(1324, 2))
La fórmula funciona para valores finitos positivos y negativos porque usa abs(value) para encontrar la magnitud, mientras que round() conserva el signo. Sigue la regla de redondeo al par de Python. Use math.isfinite() para decidir si una entrada es admitida antes de calcular el logaritmo; maneje NaN y los infinitos por separado si su aplicación los necesita.
Redondear a dígitos significativos con formateo de cadenas
El formato %g usa su precisión como conteo de dígitos significativos. Con la precisión p, usa notación científica cuando el exponente decimal es menor que -4 o mayor o igual que p; en caso contrario, usa notación ordinaria. Para la precisión 3, 0.0001 y 999 usan notación ordinaria, mientras que 0.00001 y 1000 usan notación científica. El formateo devuelve una cadena, lo que es útil cuando el objetivo es la presentación. Conserve esa cadena para preservar su representación elegida; conviértala con float() solo cuando se necesiten operaciones numéricas posteriores. Convertirla a un número descarta detalles de presentación como los ceros finales.
Por ejemplo, "%.3g" % 1324 formatea el valor con tres dígitos significativos. El resultado es texto, y la elección exacta entre notación ordinaria y científica la hace el formateador.
Redondear a dígitos significativos con sigfig
El paquete de terceros sigfig acepta la cantidad de dígitos significativos a través de su argumento sigfigs. Instale el paquete en su entorno antes de usarlo. Por ejemplo, la llamada al paquete es sigfig.round(1324, sigfigs=2). Esto es conveniente cuando el comportamiento y el formateo del paquete se ajustan a su aplicación; no es necesario para los enfoques integrados o auxiliares anteriores.
Redondear a dígitos significativos con decimal.Decimal
Decimal admite aritmética decimal y un modo de redondeo explícito. Constrúyalo a partir de una cadena cuando los dígitos decimales de la entrada importen; convertir un flotante existente no puede recuperar la información que el flotante no almacenó. Este ejemplo escala un decimal finito distinto de cero a la precisión solicitada y redondea los empates alejándose de cero con ROUND_HALF_UP.
from decimal import Decimal, ROUND_HALF_UP
def round_decimal_significant(value, digits):
if not isinstance(digits, int) or digits < 1:
raise ValueError("digits must be a positive integer")
number = Decimal(str(value))
if not number.is_finite():
raise ValueError("value must be finite")
if number.is_zero():
return number
quantum = Decimal(1).scaleb(number.adjusted() - digits + 1)
return number.quantize(quantum, rounding=ROUND_HALF_UP)
print(round_decimal_significant("1324", 2))
El resultado sigue siendo un Decimal. ROUND_HALF_UP es solo una política; elija un modo como ROUND_HALF_EVEN cuando coincida con las reglas de su aplicación. La aritmética decimal aún puede estar limitada por la precisión del contexto activo, por lo que no promete precisión ilimitada.
Redondear matrices a dígitos significativos con NumPy
NumPy es útil cuando la entrada es una matriz, pero numpy.around() acepta posiciones decimales en lugar de dígitos significativos. Para un valor finito distinto de cero, calcule el conteo de posiciones decimales con digits - 1 - floor(log10(abs(value))) y páselo a numpy.around(). Para una matriz, calcule las magnitudes elemento por elemento y maneje los ceros y los valores no finitos antes de tomar logaritmos. NumPy es una dependencia adicional; este enfoque sigue el comportamiento de redondeo de punto flotante y no conserva los ceros de presentación.
El siguiente ejemplo redondea solo los elementos finitos distintos de cero. Deja sin cambios cero, NaN y el infinito positivo o negativo. El valor devuelto es un ndarray de NumPy con elementos de punto flotante. NumPy es una dependencia adicional, así que instálelo antes de ejecutar este ejemplo.
import numpy as np
values = np.array([1234.5, -1234.5, 0.0, np.nan, np.inf, -np.inf])
digits = 3
rounded = values.copy()
finite_nonzero = np.isfinite(values) & (values != 0)
for index in np.flatnonzero(finite_nonzero):
places = digits - 1 - int(np.floor(np.log10(abs(values[index]))))
rounded[index] = np.around(values[index], decimals=places)
print(rounded.tolist())
[1230.0, -1230.0, 0.0, nan, inf, -inf]