Java: Double Machine epsilon ist nicht das kleinste x, so dass 1 + x! = 1?
Ich versuche das @ zu bestimmdouble
machine epsilon in Java unter Verwendung der Definition, dass es das kleinste darstellbare @ idouble
Wertx
so dass1.0 + x != 1.0
, genau wie in C / C ++. Laut Wikipedia ist diese Maschine epsilon gleich2^-52
(wobei 52 die Anzahl von @ idouble
Mantissenbits - 1).
Meine Implementierung verwendet dasMath.ulp()
Funktion:
double eps = Math.ulp(1.0);
System.out.println("eps = " + eps);
System.out.println("eps == 2^-52? " + (eps == Math.pow(2, -52)));
und die Ergebnisse sind, was ich erwartet hatte:
eps = 2.220446049250313E-16
eps == 2^-52? true
So weit, ist es gut. Wenn ich jedoch überprüfe, dass das angegebeneeps
ist in der Tat das kleinste x
so dass1.0 + x != 1.0
, es scheint einen kleineren zu geben, auch bekannt alsBisherig double
Wert gemäßMath.nextAfter()
:
double epsPred = Math.nextAfter(eps, Double.NEGATIVE_INFINITY);
System.out.println("epsPred = " + epsPred);
System.out.println("epsPred < eps? " + (epsPred < eps));
System.out.println("1.0 + epsPred == 1.0? " + (1.0 + epsPred == 1.0));
Welche ergibt:
epsPred = 2.2204460492503128E-16
epsPred < eps? true
1.0 + epsPred == 1.0? false
Wie wir sehen, haben wir ein kleineres als das Maschinen-Epsilon, das zu 1 addiert nicht 1 ergibt, was der Definition widerspricht.
Was stimmt also nicht mit dem allgemein akzeptierten Wert für machine epsilon gemäß dieser Definition? Oder habe ich etwas verpasst? Ich vermute einen anderen esoterischen Aspekt der Gleitkomma-Mathematik, aber ich kann nicht sehen, wo ich falsch gelaufen bin ...
BEARBEITENDanke an die Kommentatoren, ich habe es endlich geschafft. Ich habe tatsächlich die falsche Definition verwendet!eps = Math.ulp(1.0)
berechnet den Abstand zum kleinsten darstellbaren Double>1.0
, aber - und das ist der Punkt - dasseps
istnich der kleinstex
mit1.0 + x != 1.0
, sondern überzweima diesen Wert: Hinzufügen von1.0 + Math.nextAfter(eps/2)
ist gerundetobe zu1.0 + eps
.