La docstring pour numpy.finfo
définit actuellement l'attribut eps
comme:
Le plus petit nombre positif représentable tel que 1.0 + eps! = 1.0. [...]
Cette définition n'est pas correcte, du moins dans le cas courant des formats binaires IEEE 754. Par exemple, avec le format binaire64 IEEE 754 sous le mode d'arrondi habituel round-tie-to-even, la définition indiquée donne une valeur de 2**-53 + 2**-105
(environ 1.1102230246251568e-16
), ce qui est un peu plus de la moitié de la valeur correcte de 2**-52
(environ 2.220446049250313e-16
).
In [36]: eps = 2**-53 + 2**-105
In [37]: eps
Out[37]: 1.1102230246251568e-16
In [38]: 1.0 + eps != 1.0
Out[38]: True
In [39]: 1.0 + np.nextafter(eps, -np.inf) != 1.0
Out[39]: False
In [40]: np.finfo(float).eps
Out[40]: 2.2204460492503131e-16
Quelques reformulations possibles:
Le plus petit nombre positif tel que 1.0 + eps est représentable.
Ou:
La différence entre 1,0 et le plus petit flotteur représentable supérieur à 1,0.
Ou il pourrait être défini en termes de nextafter
comme:
La valeur de
np.nextafter(1.0, np.inf) - 1.0
.
A titre de comparaison, la section 5.2.4.2.2, paragraphe 11 de la norme C99 définit les différentes macros *_EPSILON
( DBL_EPSILON
, FLT_EPSILON
, ...) comme:
la différence entre 1 et la plus petite valeur supérieure à 1 qui est représentable dans le type à virgule flottante donné, b 1− p
La docstring pour epsneg
est également incorrecte.
Ah, en regardant la source , je vois que eps
est en fait calculé comme la plus petite _puissance de 2_ telle que 1 + eps != eps
. Ce n'est pas la même chose que la différence entre 1.0
et le prochain flottant représentable à partir de 1.0
, bien que les deux choses coïncident pour IEEE 754 et l'arrondi rond-pair mode. Donc mes reformulations suggérées ci-dessus ne sont pas valides. Peut-être quelque chose comme:
La plus petite puissance de 2 telle que 1.0 + eps soit représentable.
serait mieux? Techniquement, ce 2
devrait être remplacé par la base à virgule flottante, mais c'est probablement inutilement pédant. NumPy prend-il actuellement en charge les flottants radix 10 ou radix 16?
[En passant, je préfère de loin la définition de style C99 d'Epsilon, car elle n'implique que le format et ne dépend pas de la sémantique de l'addition en virgule flottante. En particulier, la définition C99 ne dépend pas du mode d'arrondi actuellement en vigueur, contrairement à la définition 1 + eps != 1
.]
Un pointeur vers np.spacing
et np.nextafter
dans la section "Voir aussi" serait également potentiellement utile.
Nous voici presque 4 ans plus tard et cela n'a pas été corrigé. Je ne pense pas que https://github.com/numpy/numpy/pull/14618 sera suffisant pour résoudre ce problème.
Pour clarifier le rapport de bogue, la définition actuelle de eps dans la docstring est décalée d'environ un facteur de 2 par rapport à la valeur de eps renvoyée par np.finfo. (Les nombres que je donne ci-dessous sont pour les implémentations avec la norme à virgule flottante IEEE-754 64 bits.) Ie,
np.finfo (1.0) .eps = 2 ** - 52 = 2,220446049250313e-16
Cependant, la docstring définit eps comme
"Le plus petit nombre positif représentable tel que 1.0 + eps! = 1.0."
La valeur réelle de eps qui satisferait la définition 1.0 + eps_min! = 1.0 est:
eps_min = 2 -53 + 2 -105 = 1.1102230246251568e-16
ce qui représente presque la moitié de la valeur actuelle de np.finfo (1.0) .eps. Nous ne voulons probablement pas changer la valeur de np.finfo (1.0) .eps, pour conserver la compatibilité ascendante, mais la définition docstring de eps doit être corrigée pour correspondre à ce qui est calculé. Le code source de np.finfo (1.0) eps utilise numpy.MachAr, et en regardant la documentation là-bas, qui autorise d'autres bases en plus de 2, je pense que la meilleure définition de eps est l'une des premières options suggérées précédemment par
"La différence entre 1.0 et le plus petit flottant représentable supérieur à 1.0. (Pour les flottants binaires 64 bits dans la norme IEEE-754, eps = 2 ** - 52 ≅ 2.22e-16.)"
La docstring pour epsneg est également incorrecte.
Je viens également de trébucher sur cette inexactitude. Cela devrait être corrigé.
Pour référence, Matlab documente son eps
(qui a la même valeur) comme: "la distance de 1.0 au prochain nombre à double précision plus grand, c'est-à-dire 2 ^ -52."
La définition actuelle est incorrecte et déroutante en raison de problèmes d'arrondi. @gwhammett la définition proposée est à la fois correcte et plus descriptive et encourage un PR à clore ce numéro.
Commentaire le plus utile
Nous voici presque 4 ans plus tard et cela n'a pas été corrigé. Je ne pense pas que https://github.com/numpy/numpy/pull/14618 sera suffisant pour résoudre ce problème.
Pour clarifier le rapport de bogue, la définition actuelle de eps dans la docstring est décalée d'environ un facteur de 2 par rapport à la valeur de eps renvoyée par np.finfo. (Les nombres que je donne ci-dessous sont pour les implémentations avec la norme à virgule flottante IEEE-754 64 bits.) Ie,
np.finfo (1.0) .eps = 2 ** - 52 = 2,220446049250313e-16
Cependant, la docstring définit eps comme
La valeur réelle de eps qui satisferait la définition 1.0 + eps_min! = 1.0 est:
eps_min = 2 -53 + 2 -105 = 1.1102230246251568e-16
ce qui représente presque la moitié de la valeur actuelle de np.finfo (1.0) .eps. Nous ne voulons probablement pas changer la valeur de np.finfo (1.0) .eps, pour conserver la compatibilité ascendante, mais la définition docstring de eps doit être corrigée pour correspondre à ce qui est calculé. Le code source de np.finfo (1.0) eps utilise numpy.MachAr, et en regardant la documentation là-bas, qui autorise d'autres bases en plus de 2, je pense que la meilleure définition de eps est l'une des premières options suggérées précédemment par
La docstring pour epsneg est également incorrecte.