Angenommen, ich habe ein float X. Ich möchte die größte Zahl finden, die kleiner als X ist und verlustfrei in einem Float gespeichert werden kann.
IIRC Der IEEE-Standard besagt, dass Sie dies tun können, indem Sie die Bits des Gleitkommas in eine int-Repräsentation konvertieren, eins subtrahieren und zurück in float konvertieren.
( edit: gilt für positive Zahlen, die nicht NaN oder inf sind. Für negative Zahlen müssen Sie hinzufügen. Siehe Rawlings Antwort für weitere Informationen.
Um zwischen den Repräsentationen zu wechseln, kenne ich nur den Operator (cast) von C #, der abgeschnitten wird. Das ist nicht was ich will.
Gibt es eine Möglichkeit, dies in C # zu tun?
Hier können Sie einfach ein float
in ein int
umwandeln, es ändern und es dann in ein float
zurückverwandeln:
BitConverter
hat dies sogar für das 64-Bit-Äquivalent eingebaut:
Peter Ruderman weist jedoch darauf hin, dass eine einfache Verringerung des zugrunde liegenden int
nicht zuverlässig ist geben Sie die nächstkleinste float
.
Insbesondere müssen Sie für negative Zahlen die Ganzzahl erhöhen , um den Gleitkommawert negativer zu machen . Für float
zero entspricht die nächstkleinste int
tatsächlich NaN
, also benötigen Sie dort einen Sonderfall.
Hier sind ein paar Funktionen, die ich zusammengelegt habe, die mit diesen Fällen im Allgemeinen umgehen sollten; es sieht auch so aus, als ob es sich vernünftig zwischen großen Zahlen und positiven / negativen Unendlichkeiten bewegt! Ich habe unsichere Konvertierungen verwendet, um die Codelänge zu reduzieren, aber Sie können bei den obigen Bytekonvertierungen bleiben, wenn Sie möchten:
%Vor%Wie Jeppe feststellt, möchten Sie wahrscheinlich auch
if (float.IsNaN(f)) return f;
, damit du nicht versehentlich einen NaN
inkrementierst oder dekrementierst und etwas gibst, das eine Zahl ist. float.PositiveInfinity
oder .NegativeInfinity
zu überprüfen, da diese mathematisch wahrscheinlich unter Inkrement / Dekrement konstant bleiben sollten. Dafür gibt es eine Bibliotheksroutine, nexttowardf(x, -INFINITY);
.
Wenn Sie dies mit Ihrem eigenen Code tun möchten, können Sie dies nativ tun (in IEEE 754 Gleitkommaoperationen, ohne auf die Fließkomma-Codierung oder Komponenten zuzugreifen), wie unten (in C) gezeigt.
Zwei Versionen werden zur Verfügung gestellt, eine, die in jedem Fall einen subnormalen Wert verwendet (bei manchen Prozessoren möglicherweise langsam) und eine, die nur dann eine Unternormale verwendet, wenn die Eingabe klein ist (aber eine Verzweigung hat). + INFINITY wird nicht als Eingabe unterstützt, obwohl Unterstützung mit einem einfachen Test hinzugefügt werden könnte. Dies ist für double
geschrieben, aber die Änderungen für float
sind einfach.
Wenn CompileMain
definiert ist, enthält es auch ein Testprogramm.
Tags und Links c# floating-point