Pergunta

Então, eu decidi tentar resolver o meu física lição de casa, escrevendo alguns scripts python para resolver problemas para mim. Um problema que eu estou correndo em é que algarismos significativos nem sempre parecem sair corretamente. Por exemplo, este alças algarismos significativos corretamente:

from decimal import Decimal
>>> Decimal('1.0') + Decimal('2.0')
Decimal("3.0")

Mas isso não:

>>> Decimal('1.00') / Decimal('3.00')
Decimal("0.3333333333333333333333333333")

Assim, duas perguntas:

  1. Am I certo de que esta não é a quantidade esperada de dígitos significativos, ou que eu preciso para retocar em matemática significativa dígitos?
  2. Existe alguma maneira de fazer isso sem ter que definir a precisão decimal manualmente? Concedido, eu tenho certeza que posso usar numpy para fazer isso, mas eu só quero saber se há uma maneira de fazer isso com o módulo decimal por curiosidade.
Foi útil?

Solução

Alterar o decimal de precisão trabalhando para 2 dígitos é não uma boa idéia, a menos que você absolutamente só vai realizar uma única operação.

Você deve sempre realizar cálculos em maior precisão do que o nível de significância, e apenas arredondar o resultado final. Se você executar uma longa sequência de cálculos e arredondar para o número de dígitos significativos em cada etapa, os erros se acumulam. O módulo decimal não sabe se qualquer operação particular é um em uma longa seqüência, ou o resultado final, por isso assume que ele não deve rodada mais do que o necessário. Idealmente seria usar precisão infinita, mas que é muito caro para que os desenvolvedores de Python resolvida por 28 dígitos.

Uma vez que você acabou de chegar ao resultado final, o que você provavelmente quer é quantize:

>>> (Decimal('1.00') / Decimal('3.00')).quantize(Decimal("0.001"))
Decimal("0.333")

Você tem que manter o controle de significado manualmente. Se você quiser rastreamento significado automática, você deve usar aritmética de intervalo. Existem algumas bibliotecas disponíveis para Python, incluindo pyinterval e mpmath (que suporta precisão arbitrária). Também é simples de implementar aritmética intervalo com a biblioteca decimal, uma vez que suporta dirigido arredondamento.

Você também pode querer ler o Decimal Aritmética FAQ: É a aritmética decimal 'significado' aritmética?

Outras dicas

Decimals não vai jogar fora casas decimais assim. Se você realmente quiser precisão limite para 2 D.P. tente

decimal.getcontext().prec=2

EDIT:. Você pode, alternativamente, chamar quantize () cada vez que você multiplicar ou dividir (adição e subtração irá preservar os 2 dps)

Só por curiosidade ... é necessário utilizar o módulo decimal? Por que não ponto flutuante com uma significativa figuras arredondamento de números quando você está pronto para vê-los? Ou você está tentando manter o controle das figuras significativas da computação (como quando você tem que fazer uma análise de erro de um resultado, calculando o erro calculado em função das incertezas que entraram no cálculo)? Se você quer uma função de arredondamento que rounds da esquerda do número em vez do direito, tente:

def lround(x,leadingDigits=0): 
    """Return x either as 'print' would show it (the default) 
    or rounded to the specified digit as counted from the leftmost 
    non-zero digit of the number, e.g. lround(0.00326,2) --> 0.0033
    """ 
    assert leadingDigits>=0 
    if leadingDigits==0: 
            return float(str(x)) #just give it back like 'print' would give it
    return float('%.*e' % (int(leadingDigits),x)) #give it back as rounded by the %e format  

Os números vai olhar direito quando você imprimi-los ou convertê-los para cordas, mas se você está trabalhando no prompt e não imprimi-los explicitamente que pode parecer um pouco estranho:

>>> lround(1./3.,2),str(lround(1./3.,2)),str(lround(1./3.,4))
(0.33000000000000002, '0.33', '0.3333')

defaults decimal para 28 lugares de precisão.
A única maneira de limitar o número de dígitos que retorna é alterando a precisão.

Se eu undertand Decimal corretamente, a "precisão" é o número de dígitos depois do ponto decimal no decimal notação .

Você parece querer outra coisa: o número de dígitos significativos. Essa é um a mais que o número de dígitos depois do ponto decimal no notação científica .

Eu estaria interessado em aprender sobre um módulo Python que faz significativas dígitos-Aware cálculos de ponto em ponto flutuante.

errada do que com o ponto flutuante?

>>> "%8.2e"%  ( 1.0/3.0 )
'3.33e-01'

Foi projetada para cálculos de estilo científico com um número limitado de dígitos significativos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top