Question

J'ai donc décidé d'essayer de résoudre mes devoirs de physique en écrivant des scripts en python pour résoudre des problèmes pour moi. Un problème que je rencontre est que les chiffres significatifs ne semblent pas toujours sortir correctement. Par exemple, cela gère correctement les chiffres significatifs:

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

Mais cela ne veut pas:

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

Donc deux questions:

  1. Ai-je raison de penser que ce n'est pas le nombre attendu de chiffres significatifs, ou dois-je rafraîchir mon calcul mathématique des chiffres significatifs?
  2. Y a-t-il un moyen de le faire sans avoir à régler manuellement la précision décimale? Bien sûr, je peux utiliser numpy pour cela, mais je veux juste savoir s’il est possible de faire cela avec le module décimal par curiosité.
Était-ce utile?

La solution

Modifier la précision de travail décimale à 2 chiffres n'est pas une bonne idée, à moins que vous n'ayez absolument à effectuer qu'une seule opération.

Vous devez toujours effectuer des calculs avec une précision supérieure au niveau de signification et uniquement autour du résultat final. Si vous effectuez une longue séquence de calculs et arrondissez au nombre de chiffres significatifs à chaque étape, les erreurs s’accumuleront. Le module décimal ne sait pas si une opération particulière fait partie d'une longue séquence ou du résultat final. Il suppose donc qu'elle ne devrait pas arrondir plus que nécessaire. Idéalement, il utiliserait une précision infinie, mais comme cela coûte trop cher, les développeurs Python ont opté pour 28 chiffres.

Une fois que vous êtes arrivé au résultat final, ce que vous voulez probablement, c'est quantifier:

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

Vous devez suivre l’importance manuellement. Si vous souhaitez un suivi automatique de l'importance, vous devez utiliser l'arithmétique d'intervalle. Certaines bibliothèques sont disponibles pour Python, notamment pyinterval et mpmath (qui prend en charge la précision arbitraire). Il est également simple de mettre en œuvre une arithmétique par intervalles avec la bibliothèque décimale, car elle prend en charge l’arrondi dirigé.

Vous pouvez également consulter la FAQ sur l'arithmétique décimale: L'arithmétique décimale est-elle une arithmétique?

Autres conseils

Les décimales ne jetteront pas les décimales de ce genre. Si vous voulez vraiment limiter la précision à 2 d.p. puis essayez

decimal.getcontext().prec=2

EDIT: Vous pouvez également appeler quantize () chaque fois que vous multipliez ou divisez (l’addition et la soustraction préservent les 2 dps).

Juste par curiosité ... est-il nécessaire d'utiliser le module décimal? Pourquoi ne pas virgule flottante avec chiffres arrondis lorsque vous êtes prêt à les voir? Ou essayez-vous de garder une trace des chiffres significatifs du calcul (comme lorsque vous devez effectuer une analyse d'erreur d'un résultat, calculer l'erreur calculée en fonction des incertitudes prises en compte dans le calcul)? Si vous souhaitez une fonction d’arrondi arrondie à partir de la gauche du nombre au lieu de la droite, essayez:

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  

Les chiffres auront l'air correct lorsque vous les imprimerez ou les convertirez en chaînes, mais si vous travaillez à l'invite et que vous ne les imprimez pas explicitement, ils peuvent paraître un peu étranges:

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

La virgule par défaut est 28 positions de précision.
Le seul moyen de limiter le nombre de chiffres renvoyés est de modifier la précision.

Si je comprends correctement Decimal, la "précision" est le nombre de chiffres après le point décimal de la notation décimale .

Vous semblez vouloir autre chose: le nombre de chiffres significatifs. C'est un de plus que le nombre de chiffres après la virgule dans la notation scientifique .

J'aimerais en savoir plus sur un module Python qui effectue des calculs en virgule flottante tenant compte des chiffres significatifs.

Quel est le problème avec virgule flottante?

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

Il a été conçu pour des calculs de type scientifique avec un nombre limité de chiffres significatifs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top