Domanda

Quindi ho deciso di provare a risolvere i miei compiti di fisica scrivendo alcuni script Python per risolvere i problemi per me. Un problema in cui mi imbatto è che cifre significative non sembrano sempre emergere correttamente. Ad esempio, questo gestisce correttamente cifre significative:

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

Ma questo non:

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

Quindi due domande:

  1. Ho ragione sul fatto che questa non è la quantità prevista di cifre significative o devo ripassare su calcoli matematici significativi?
  2. Esiste un modo per farlo senza dover impostare manualmente la precisione decimale? Certo, sono sicuro di poter usare numpy per farlo, ma voglio solo sapere se c'è un modo per farlo con il modulo decimale per curiosità.
È stato utile?

Soluzione

Cambiare la precisione decimale di lavoro a 2 cifre è non una buona idea, a meno che non si esegua assolutamente un'unica operazione.

Dovresti sempre eseguire calcoli con una precisione maggiore rispetto al livello di significatività e arrotondare solo il risultato finale. Se si esegue una lunga sequenza di calcoli e si arrotonda al numero di cifre significative in ciascun passaggio, si accumuleranno errori. Il modulo decimale non sa se una determinata operazione è una in una lunga sequenza o il risultato finale, quindi presume che non dovrebbe arrotondare più del necessario. Idealmente userebbe una precisione infinita, ma è troppo costoso, quindi gli sviluppatori di Python si sono stabiliti per 28 cifre.

Una volta arrivato al risultato finale, quello che probabilmente vuoi è quantizzare:

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

Devi tenere traccia manualmente del significato. Se si desidera il rilevamento automatico del significato, è necessario utilizzare l'aritmetica degli intervalli. Ci sono alcune librerie disponibili per Python, tra cui pyinterval e mpmath (che supporta la precisione arbitraria). È anche semplice implementare l'aritmetica degli intervalli con la libreria decimale, poiché supporta l'arrotondamento diretto.

Puoi anche leggere le Domande frequenti sull'aritmetica decimale: è l'aritmetica decimale & # 8216; significato & # 8217; aritmetica?

Altri suggerimenti

I decimali non eliminano i decimali in questo modo. Se vuoi davvero limitare la precisione a 2 d.p. quindi prova

decimal.getcontext().prec=2

EDIT: in alternativa puoi chiamare quantize () ogni volta che moltiplichi o dividi (addizione e sottrazione conserveranno i 2 dps).

Solo per curiosità ... è necessario utilizzare il modulo decimale? Perché non virare in virgola mobile con cifre arrotondate di cifre significative quando si è pronti a vederle? Oppure stai cercando di tenere traccia delle cifre significative del calcolo (come quando devi fare un'analisi degli errori di un risultato, calcolando l'errore calcolato in funzione delle incertezze che sono andate nel calcolo)? Se vuoi una funzione di arrotondamento che arrotonda da sinistra del numero invece che da destra, prova:

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  

I numeri appariranno giusti quando li stampi o li converti in stringhe, ma se stai lavorando al prompt e non li stampi esplicitamente, potrebbero sembrare un po 'strani:

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

Il valore predefinito decimale è 28 posizioni di precisione.
L'unico modo per limitare il numero di cifre che restituisce è modificando la precisione.

Se ho capito correttamente il decimale, la "precisione" è il numero di cifre dopo il punto decimale nella notazione decimale .

Sembra che tu voglia qualcos'altro: il numero di cifre significative. Questo è uno in più rispetto al numero di cifre dopo il punto decimale nella notazione scientifica .

Sarei interessato a conoscere un modulo Python che esegue calcoli in virgola mobile con cifre significative.

Cosa c'è che non va in virgola mobile?

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

È stato progettato per calcoli di tipo scientifico con un numero limitato di cifre significative.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top