python numpy machine epsilon


103

J'essaie de comprendre ce qu'est la machine epsilon. Selon Wikipedia, il peut être calculé comme suit:

def machineEpsilon(func=float):
    machine_epsilon = func(1)
    while func(1)+func(machine_epsilon) != func(1):
        machine_epsilon_last = machine_epsilon
        machine_epsilon = func(machine_epsilon) / func(2)
    return machine_epsilon_last

Cependant, il ne convient que pour les nombres à double précision. Je suis intéressé à le modifier pour prendre en charge également les nombres à simple précision. J'ai lu que numpy peut être utilisé, en particulier la numpy.float32classe. Quelqu'un peut-il aider à modifier la fonction?


8
Cette fonction est suffisamment générale pour fonctionner avec toutes les précisions. Passez simplement a numpy.float32comme argument à la fonction!
— David Zwicker

Réponses:


192

Un moyen plus simple d'obtenir la machine epsilon pour un type de flotteur donné est d'utiliser np.finfo():

print(np.finfo(float).eps)
# 2.22044604925e-16

print(np.finfo(np.float32).eps)
# 1.19209e-07

3
juste pour être sûr à 100%, le premier fournit la précision "standard" python des flotteurs innés tandis que le second la précision des flotteurs de numpy?
— Charlie Parker

2
notez que la précision standard de numpy est de 64 (dans un ordinateur 64 bits): >>> print(np.finfo(np.float).eps) = 2.22044604925e-16 et >>> print(np.finfo(np.float64).eps) = 2.22044604925e-16
— Charlie Parker

2
@CharlieParker J'aurais pu utiliser à la np.floatplace, car c'est juste un alias de la fonction intégrée de Python float. Les flottants Python sont 64 bits (C double) sur presque toutes les plates-formes. floatet ont np.float64donc généralement une précision équivalente, et dans la plupart des cas, vous pouvez les utiliser de manière interchangeable. Cependant, ils ne sont pas identiques - np.float64c'est un type spécifique à numpy, et un np.float64scalaire a des méthodes différentes d'un floatscalaire natif . Comme vous vous en doutez, np.float32c'est un flottant 32 bits.
— ali_m

92

Un autre moyen simple d'obtenir epsilon est:

In [1]: 7./3 - 4./3 -1
Out[1]: 2.220446049250313e-16

4
Ouais, et pourquoi 8./3 - 5./3 - 1cède-t-il -eps, 4./3 - 1./3 - 1donne zéro et 10./3 - 7./3 - 1rapporte zéro?
— Steve Tjoa

20
Ah, la réponse est ici, Problème 3: rstudio-pubs-static.s3.amazonaws.com/ ... En gros, si vous soustrayez la représentation binaire de 4/3 de 7/3, vous obtenez la définition de la machine epsilon. Je suppose donc que cela devrait s'appliquer à n'importe quelle plate-forme.
— Steve Tjoa

13
C'est trop ésotérique d'une réponse qui nécessite trop de connaissances de Python et des éléments numpyinternes lorsqu'il existe une numpyfonction existante pour trouver l'epsilon.
— Olga Botvinnik

29
Cette réponse ne nécessite aucune connaissance de Python ou des composants internes de numpy.
— GuillaumeDufay

5
En effet, il affirme que le lecteur est conscient du fait que Python s'exécute sur des ordinateurs qui n'utilisent pas le calcul de base 3 sous-jacent.
— kokociel

17

Cela fonctionnera déjà, comme l'a souligné David!

>>> def machineEpsilon(func=float):
...     machine_epsilon = func(1)
...     while func(1)+func(machine_epsilon) != func(1):
...         machine_epsilon_last = machine_epsilon
...         machine_epsilon = func(machine_epsilon) / func(2)
...     return machine_epsilon_last
... 
>>> machineEpsilon(float)
2.220446049250313e-16
>>> import numpy
>>> machineEpsilon(numpy.float64)
2.2204460492503131e-16
>>> machineEpsilon(numpy.float32)
1.1920929e-07

btw votre fonction augmentera NameErrorsi la condition dans whilesera satisfaite lors de la première vérification, il est donc probablement logique de le faire machine_epsilon = machine_epsilon_last = func(1)dans la première instruction
— Azat Ibrakov
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.