Die Dokumentzeichenfolge für numpy.finfo
definiert derzeit das Attribut eps
als:
Die kleinste darstellbare positive Zahl, so dass 1,0 + eps! = 1,0. [...]
Diese Definition ist zumindest im allgemeinen Fall der IEEE 754-Binärformate nicht korrekt. Beispielsweise ergibt die angegebene Definition mit dem IEEE 754-Binär64-Format im üblichen Rundungsmodus mit gerader Bindung einen geraden Wert von 2**-53 + 2**-105
(ca. 1.1102230246251568e-16
), was ein wenig ist mehr als die Hälfte des korrekten Wertes von 2**-52
(ca. 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
Einige mögliche Umformulierungen:
Die kleinste positive Zahl, so dass 1,0 + eps darstellbar ist.
Oder:
Die Differenz zwischen 1,0 und dem kleinsten darstellbaren Float ist größer als 1,0.
Oder es könnte definiert werden als nextafter
als:
Der Wert von
np.nextafter(1.0, np.inf) - 1.0
.
Zum Vergleich definiert Abschnitt 5.2.4.2.2, Absatz 11 des C99-Standards die verschiedenen *_EPSILON
Makros ( DBL_EPSILON
, FLT_EPSILON
, ...) wie folgt:
die Differenz zwischen 1 und dem kleinsten Wert größer als 1, der im gegebenen Gleitkommatyp darstellbar ist, b 1 - p
Die Dokumentzeichenfolge für epsneg
ist ebenfalls falsch.
Ah, wenn ich mir die Quelle ansehe, sehe ich, dass eps
tatsächlich als die kleinste Potenz von 2 berechnet wird, so dass 1 + eps != eps
. Das ist nicht das Gleiche wie der Unterschied zwischen 1.0
und dem nächsten darstellbaren Float von 1.0
, obwohl die beiden Dinge zufällig für IEEE 754 und die Rundung auf die Gleichmäßigkeit zusammenfallen Modus. Daher sind meine oben vorgeschlagenen Umformulierungen ungültig. Vielleicht so etwas wie:
Die kleinste Potenz von 2, so dass 1,0 + eps darstellbar ist.
wäre besser? Technisch gesehen sollte 2
durch den Gleitkomma-Radix ersetzt werden, aber das ist wahrscheinlich unnötig pedantisch. Unterstützt NumPy derzeit Radix 10- oder Radix 16-Floats?
[Abgesehen davon bevorzuge ich die C99-Definition von epsilon sehr, da sie nur das Format betrifft und nicht von der Semantik der Gleitkommaaddition abhängt. Insbesondere hängt die C99-Definition nicht vom aktuell gültigen Rundungsmodus ab, während dies 1 + eps != 1
Definition von
Ein Zeiger auf np.spacing
und np.nextafter
im Abschnitt "Siehe auch" wäre möglicherweise ebenfalls nützlich.
Hier sind wir fast 4 Jahre später und dies wurde nicht behoben. Ich denke nicht, dass https://github.com/numpy/numpy/pull/14618 ausreichen wird, um dieses Problem zu schließen.
Um den Fehlerbericht zu verdeutlichen, ist die aktuelle Definition von eps in der Dokumentzeichenfolge um den Faktor 2 vom Wert des von np.finfo zurückgegebenen eps abweichen. (Die Zahlen, die ich unten gebe, gelten für Implementierungen mit dem 64-Bit-Gleitkomma-Standard IEEE-754.)
np.finfo (1.0) .eps = 2 ** - 52 = 2.220446049250313e-16
Die Dokumentzeichenfolge definiert eps jedoch als
"Die kleinste darstellbare positive Zahl, so dass 1,0 + eps! = 1,0."
Der tatsächliche Wert von eps, der die Definition 1.0 + eps_min! = 1.0 erfüllen würde, ist:
eps_min = 2 -53 + 2 -105 = 1.1102230246251568e-16
Das ist fast die Hälfte des Barwerts von np.finfo (1.0) .eps. Wir möchten den Wert von np.finfo (1.0) .eps wahrscheinlich nicht ändern, um die Abwärtskompatibilität zu gewährleisten, aber die Docstring-Definition von eps muss korrigiert werden, damit sie mit den berechneten Werten übereinstimmt. Der Quellcode für np.finfo (1.0) eps verwendet numpy.MachAr. Wenn ich mir die Dokumentation dort ansehe, die neben 2 noch andere Grundlagen zulässt, denke ich, dass die beste Definition von eps eine der frühen Optionen ist, die @mdickinson zuvor vorgeschlagen hat. Ich würde der Beschreibung auch einen Beispielwert hinzufügen:
"Der Unterschied zwischen 1,0 und dem kleinsten darstellbaren Float ist größer als 1,0. (Für binäre 64-Bit-Floats im IEEE-754-Standard ist eps = 2 ** - 52 ≅ 2,22e-16.)"
Die Dokumentzeichenfolge für epsneg ist ebenfalls falsch.
Ich bin auch nur über diese Ungenauigkeit gestolpert. Dies sollte behoben werden.
Als Referenz dokumentiert Matlab sein eps
(das den gleichen Wert hat) wie folgt: "Der Abstand von 1,0 zur nächstgrößeren Zahl mit doppelter Genauigkeit, dh 2 ^ -52."
Die aktuelle Definition ist aufgrund von Rundungsproblemen falsch und verwirrend. @gwhammett Die vorgeschlagene Definition ist sowohl korrekt als auch
Hilfreichster Kommentar
Hier sind wir fast 4 Jahre später und dies wurde nicht behoben. Ich denke nicht, dass https://github.com/numpy/numpy/pull/14618 ausreichen wird, um dieses Problem zu schließen.
Um den Fehlerbericht zu verdeutlichen, ist die aktuelle Definition von eps in der Dokumentzeichenfolge um den Faktor 2 vom Wert des von np.finfo zurückgegebenen eps abweichen. (Die Zahlen, die ich unten gebe, gelten für Implementierungen mit dem 64-Bit-Gleitkomma-Standard IEEE-754.)
np.finfo (1.0) .eps = 2 ** - 52 = 2.220446049250313e-16
Die Dokumentzeichenfolge definiert eps jedoch als
Der tatsächliche Wert von eps, der die Definition 1.0 + eps_min! = 1.0 erfüllen würde, ist:
eps_min = 2 -53 + 2 -105 = 1.1102230246251568e-16
Das ist fast die Hälfte des Barwerts von np.finfo (1.0) .eps. Wir möchten den Wert von np.finfo (1.0) .eps wahrscheinlich nicht ändern, um die Abwärtskompatibilität zu gewährleisten, aber die Docstring-Definition von eps muss korrigiert werden, damit sie mit den berechneten Werten übereinstimmt. Der Quellcode für np.finfo (1.0) eps verwendet numpy.MachAr. Wenn ich mir die Dokumentation dort ansehe, die neben 2 noch andere Grundlagen zulässt, denke ich, dass die beste Definition von eps eine der frühen Optionen ist, die @mdickinson zuvor vorgeschlagen hat. Ich würde der Beschreibung auch einen Beispielwert hinzufügen:
Die Dokumentzeichenfolge für epsneg ist ebenfalls falsch.