HOWTO · Python

Como arredondar um número para dígitos significativos em Python

Aprenda a arredondar números do Python para dígitos significativos com round(), math, formatação, Decimal, sigfig e NumPy.

Nesta página

Para arredondar um número para uma quantidade escolhida de dígitos significativos, encontre sua magnitude decimal e passe a contagem de casas decimais correspondente para round(). Por exemplo, 1.342 arredondado para um dígito significativo torna-se 1.000. A função integrada é suficiente para um único valor; use uma função auxiliar para cálculos repetidos, formatação quando o resultado deve permanecer como texto, Decimal quando as regras de arredondamento decimal importam, ou NumPy para matrizes.

Arredondar para dígitos significativos com o round() do Python’s

round(number, ndigits) arredonda para uma quantidade de casas decimais. Para dígitos significativos, calcule ndigits como digits - 1 - floor(log10(abs(number))). Para 1.342 e um dígito significativo, isso é 1 - 1 - 3, ou -3, então o Python arredonda para o milhar mais próximo.

Execute este exemplo:

print(round(1342, -3))
1000

O Python usa o arredondamento para o par (ties-to-even) para casos exatamente no meio, de modo que o último dígito retido é par quando o valor está exatamente no meio entre dois valores arredondados. Isso é diferente de arredondar sempre um empate para longe de zero. Um ndigits negativo arredonda para dezenas, centenas ou potências de dez maiores. round() retorna um número; ele não preserva zeros à direita como convenção de exibição. Para entradas de ponto flutuante, a aproximação binária armazenada também pode afetar empates decimais aparentes.

Arredondar para dígitos significativos com uma função auxiliar de math

Uma função auxiliar pode calcular a contagem de casas decimais a partir da magnitude em base 10. A versão a seguir aceita contagens de dígitos inteiros positivos e valores numéricos finitos, e retorna zero inalterado. Ela levanta ValueError para uma contagem de dígitos não suportada ou uma entrada não finita, já que log10() não pode determinar uma magnitude decimal finita para esses 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))

A fórmula funciona para valores finitos positivos e negativos porque usa abs(value) para encontrar a magnitude, enquanto round() preserva o sinal. Ela segue a regra de arredondamento para o par do Python. Use math.isfinite() para decidir se uma entrada é suportada antes de calcular o logaritmo; trate NaN e infinitos separadamente se seu aplicativo precisar deles.

Arredondar para dígitos significativos com formatação de string

O formato %g usa sua precisão como uma contagem de dígitos significativos. Com a precisão p, ele usa notação científica quando o expoente decimal é menor que -4 ou maior ou igual a p; caso contrário, usa notação comum. Para a precisão 3, 0.0001 e 999 usam notação comum, enquanto 0.00001 e 1000 usam notação científica. A formatação retorna uma string, o que é útil quando o objetivo é a apresentação. Mantenha essa string para preservar sua representação escolhida; converta-a com float() apenas quando operações numéricas posteriores forem necessárias. Converter para um número descarta detalhes de exibição, como zeros à direita.

Por exemplo, "%.3g" % 1324 formata o valor com três dígitos significativos. O resultado é texto, e a escolha exata entre notação comum e científica é feita pelo formatador.

Arredondar para dígitos significativos com sigfig

O pacote de terceiros sigfig aceita a quantidade de dígitos significativos por meio de seu argumento sigfigs. Instale o pacote em seu ambiente antes de usá-lo. Por exemplo, a chamada ao pacote é sigfig.round(1324, sigfigs=2). Isso é conveniente quando o comportamento e a formatação do pacote se adequam ao seu aplicativo; não é necessário para as abordagens integradas ou auxiliares acima.

Arredondar para dígitos significativos com decimal.Decimal

Decimal suporta aritmética decimal e um modo de arredondamento explícito. Construa-o a partir de uma string quando os dígitos decimais na entrada importarem; converter um float existente não pode recuperar informações que o float não armazenou. Este exemplo escala um decimal finito diferente de zero para a precisão solicitada e arredonda empates para longe de zero com 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))

O resultado permanece um Decimal. ROUND_HALF_UP é apenas uma política; escolha um modo como ROUND_HALF_EVEN quando ele corresponder às regras do seu aplicativo. A aritmética decimal ainda pode ser limitada pela precisão do contexto ativo, portanto não promete precisão ilimitada.

Arredondar matrizes para dígitos significativos com NumPy

O NumPy é útil quando a entrada é uma matriz, mas numpy.around() aceita casas decimais em vez de dígitos significativos. Para um valor finito diferente de zero, calcule a contagem de casas decimais com digits - 1 - floor(log10(abs(value))) e passe-a para numpy.around(). Para uma matriz, calcule as magnitudes elemento por elemento e trate zeros e valores não finitos antes de tomar logaritmos. O NumPy é uma dependência adicional; essa abordagem segue o comportamento de arredondamento de ponto flutuante e não preserva zeros de exibição.

O exemplo abaixo arredonda apenas elementos finitos diferentes de zero. Ele deixa zero, NaN e infinito positivo ou negativo inalterados. O valor retornado é um ndarray do NumPy com elementos de ponto flutuante. O NumPy é uma dependência adicional, então instale-o antes de executar este exemplo.

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]