Warf hat geschrieben: Mi 4. Sep 2024, 19:04
Die LibC variante wird zwar vermutlich deutlich effizienter implementiert sein, man kann das ganze aber auch recht trivial selbst in Pascal bauen:
Code: Alles auswählen
function nextAfter(const AValue: Single): Single;
var
Sign, Exp, Mantissa: LongWord;
begin
// Single precision float: 8 bit exponent 23 bit mantissa
Sign := LongWord(aValue) and (1 shl 31);
Exp := LongWord(aValue) and (255 shl 23);
Mantissa := LongWord(aValue) and ((1 shl 23) - 1);
if Mantissa + 1 < 1 shl 23 then
PLongWord(@Result)^ := Sign Or Exp Or (Mantissa + 1)
else if Exp + 1 < 256 then
PLongWord(@Result)^ := Sign Or (Exp+1)
else if Sign = 0 then
Result := Infinity
else
Result := NegInfinity;
end;
function nextAfter(const AValue: Double): Double;
var
Sign, Exp, Mantissa: QWord;
begin
// Double precision float: 11 bit exponent 52 bit mantissa
Sign := QWord(aValue) and (1 shl 63);
Exp := QWord(aValue) and (2047 shl 52);
Mantissa := QWord(aValue) and ((1 shl 52) - 1);
if Mantissa + 1 < 1 shl 52 then
PQWord(@Result)^ := Sign Or Exp Or (Mantissa + 1)
else if Exp + 1 < 2048 then
PQWord(@Result)^ := Sign Or (Exp+1)
else if Sign = 0 then
Result := Infinity
else
Result := NegInfinity;
end;
Vielen Dank für dieses Beispiel, welches grob getestet das gleiche Ergebnis liefert. Was bei dem "Original" _nextafter schön ist, dass man auch die Richtung angeben kann, also nicht nur die nächstgrößere, sondern auch die nächstkleinere Zahl ermitteln kann.
Bei der ganzen Aktion ist mir gerade aufgefallen, dass die in der Unit Math angegebene
MinDouble = 2.2250738585072014e-308;
tatsächlich gar nicht die kleinste mögliche Zahl ist. Im dort angegebenen Wikipedia-Artikel
https://en.wikipedia.org/wiki/Double-pr ... n_examples ist diese Zahl zwar auch angegeben, zusätzlich aber auch die in unseren Versuchen ermittelte:
4.9406564584124654E−324 (Min. subnormal positive double)
Im Text darüber steht: "By compromising precision, the subnormal representation allows even smaller values up to about 5 × 10−324".
Ich hätte eigentlich erwartet, das MinDouble die kleinstmögliche Double-Zahl ist.
Bei Delphi ist die MinDouble auch so definiert.
Ich könnte mir vorstellen, dass Programme die die Konstante verwenden, deutlich unterschiedliche Ergebnisse liefern, wenn sie mit Delphi oder FPC/Lazarus compiliert werden.
Ist das ein FPC/Lazarus Bug?