Para responder diretamente à pergunta, aqui está minha versão usando a nomeação da função R :
import math
def signif(x, digits=6):
if x == 0 or not math.isfinite(x):
return x
digits -= math.ceil(math.log10(abs(x)))
return round(x, digits)
Meu principal motivo para postar esta resposta são os comentários reclamando que "0,075" arredonda para 0,07 em vez de 0,08. Isso se deve, como apontado por "Iniciante C", a uma combinação de aritmética de ponto flutuante com precisão finita e uma representação de base 2 . O número mais próximo a 0,075 que pode realmente ser representado é um pouco menor; portanto, o arredondamento sai de maneira diferente do que você pode esperar ingenuamente.
Observe também que isso se aplica a qualquer uso de aritmética de ponto flutuante não decimal, por exemplo, C e Java têm o mesmo problema.
Para mostrar com mais detalhes, pedimos ao Python que formate o número no formato "hexadecimal":
0.075.hex()
o que nos dá: 0x1.3333333333333p-4
. A razão para fazer isso é que a representação decimal normal geralmente envolve arredondamentos e, portanto, não é como o computador "vê" o número. Se você não está acostumado a este formato, um par de referências úteis são os docs Python eo padrão C .
Para mostrar como esses números funcionam um pouco, podemos voltar ao nosso ponto de partida fazendo:
0x13333333333333 / 16**13 * 2**-4
que deve ser impresso 0.075
. 16**13
é porque existem 13 dígitos hexadecimais após o ponto decimal e 2**-4
porque os expoentes hexadecimais são base-2.
Agora, temos uma idéia de como os carros alegóricos são representados. Podemos usar o decimal
módulo para fornecer mais precisão, mostrando o que está acontecendo:
from decimal import Decimal
Decimal(0x13333333333333) / 16**13 / 2**4
dando: 0.07499999999999999722444243844
e esperançosamente explicando por que round(0.075, 2)
avalia0.07