ich suche eine FPC-Funktion, die der C-Funktion nextafter entspricht.
Diese Funktion liefert zu einer gegebenen Fließkommazahl die nächstgrößere bzw. nächstkleinere zurück.
Im Prinzip läuft es darauf hinaus, in der Mantisse das unterste Bit zu manipulieren, muss aber dabei natürlich die Überläufe im Exponenten berücksichtigen.
Der Sinn der Sache ist folgender.
Will man eine Ebene lückenlos mit Rechtecken pflastern, so dürfen keine Punkte der Ebene in mehr als einem Rechteck liegen.
Hierzu definiert man das Rechteck so, dass die jeweils rechte (und untere) Seite nicht mehr zum Rechteck gehören.
Beispiel (nur die X-Achse betrachtet):
Rechteck 1: Links: 10.0, Rechts: 16.0
Rechteck 2: Links: 16.0, Rechts: 30.0
Ein Punkt mit der x-Koordinate 16.0 liegt nach dieser Definition in Rechteck 2.
Das lässt sich einfach programmieren:
Code: Alles auswählen
if (x >= r.Left) and (x < r.Right) then Result := True;
Die Antwort darauf liefert eben genau die gesuchte Funktion:
d := nextafter(16.0,10.0);
Durch geduldiges Spielen im Debugger kommt man auf das Ergebnis: 15,9999999999999980
Und eine kleinere Differenz ist nicht mehr möglich.
Nur hätte ich das gerne berechnet und nicht ausprobiert.
Vielen Dank!
Hier mein Bastelprogramm:
Man braucht ein Form, einen Button und ein Memo
Code: Alles auswählen
procedure TForm1.Button1Click(Sender: TObject);
var
d1 : Double; // Die zu manipulierende Double
b : array[0..SizeOf(d1)-1] of Byte absolute d1; // Die Bits des Double
d0 : Double; // Die Ausgangs double
i : Integer;
s : String;
begin
s := '';
d0 := 16.0; // Geht nur mit sehr speziellen Zahlen, bspw. 10.0 oder 20.0!!
memo1.Lines.Add(Format('%16.16f',[d0])); // 16,0000000000000000
d1 := d0; // Die Ausgangszahl der manipulierenden Double zuweisen
// durch die Deklaration "absolute" liegen die Werte auch im array b
for i := 0 to High(b) do
s := s + Format(' %2.2x',[b[i]]); // Hex zahlen zusammenstellen
memo1.Lines.Add(Format('%1.16f als HexDump %s',[d1,s])); // ausgeben
// Jetzt die Bits manipulieren
for i := 0 to 5 do
b[i] := $FF;
b[6] := b[6] - 1;
s := '';
for i := 0 to High(b) do
s := s + Format(' %2.2x',[b[i]]);
memo1.Lines.Add(Format('%1.16f als HexDump %s',[d1,s])); // ausgeben
memo1.Lines.Add(Format('Differenz: %1.6g',[d0-d1])); // -1,77636E-15
end;
16,0000000000000000
16,0000000000000000 als HexDump 00 00 00 00 00 00 30 40
15,9999999999999980 als HexDump FF FF FF FF FF FF 2F 40
Differenz: 1,77636E-15