web-dev-qa-db-fra.com

Epsilon machine en Python

Un manuel que j'étudie actuellement (je suis un débutant) dit:

"Les nombres qui diffèrent de moins que la machine epsilon sont numériquement les mêmes"

Avec Python, la machine epsilon pour les valeurs flottantes peut être obtenue en tapant

eps = numpy.finfo(float).eps

Maintenant, si je vérifie

1 + eps/10 != 1

J'obtiens Faux.

Mais si je vérifie

0.1 + eps/10 != 0.1

J'obtiens True.

Ma dernière expression logique devient fausse si je divise eps par 100. Alors, comment fonctionne epsilon machine? La documentation Python dit simplement

"Le plus petit nombre positif représentable tel que 1.0 + eps! = 1.0. Le type de eps est un type à virgule flottante approprié."

Merci d'avance.

12
Charlie

Les nombres à virgule flottante ont une certaine précision, à quelques décimales près en notation scientifique. Plus le nombre est grand, plus le chiffre le moins significatif est grand dans cette représentation, et donc plus le "epsilon" qui pourrait contribuer à ce nombre est grand.

Ainsi, l'epsilon est relatif au nombre auquel il est ajouté, ce qui est en fait indiqué dans la documentation que vous avez citée: "... tel que 1.0 + eps! = 1.0". Si le numéro de "référence" est plus petit de, par ex. un ordre de grandeur, puis eps est également plus petit.

Si ce n'était pas le cas, vous ne pouviez pas calculer pas du tout avec des nombres inférieurs à eps (2.2e-16 dans mon cas).

9
tobias_k

Dans ce cas, vous ne voulez vraiment pas np.finfo. Ce que vous voulez, c'est np.spacing, qui calcule la distance entre l'entrée et le prochain plus grand nombre qui peut être représenté exactement.

Essentiellement, np.spacing calcule "eps" pour un nombre donné. Il utilise le type de données du nombre (natif python flottants sont des flottants 64 bits), donc un np.float32 ou np.float16 donnera une réponse différente de celle d'un flottant 64 bits.

Par exemple:

import numpy as np

print 'Float64, 1.0 -->', np.spacing(1.0)
print 'Float64, 1e12 -->', np.spacing(1e12)
print 'Float64, 1e-12 -->', np.spacing(1e-12)
print ''
print 'Float32, 1.0 -->', np.spacing(np.float32(1.0))
print 'Float32, 1e12 -->', np.spacing(np.float32(1e12))
print 'Float32, 1e-12 -->', np.spacing(np.float32(1e-12))

Ce qui donne:

Float64, 1.0 --> 2.22044604925e-16
Float64, 1e12 --> 0.0001220703125
Float64, 1e-12 --> 2.01948391737e-28

Float32, 1.0 --> 1.19209e-07
Float32, 1e12 --> 65536.0
Float32, 1e-12 --> 1.0842e-19
10
Joe Kington