Finde den Gleitkommawert direkt unter einem Wert

8

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?

    
tenpn 11.01.2013, 12:29
quelle

2 Antworten

6

Hier können Sie einfach ein float in ein int umwandeln, es ändern und es dann in ein float zurückverwandeln:

%Vor%

BitConverter hat dies sogar für das 64-Bit-Äquivalent eingebaut:

%Vor%

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

  • Beginne jede Funktion mit if (float.IsNaN(f)) return f; , damit du nicht versehentlich einen NaN inkrementierst oder dekrementierst und etwas gibst, das eine Zahl ist.
  • Denken Sie auch daran, die Eingabe gegen float.PositiveInfinity oder .NegativeInfinity zu überprüfen, da diese mathematisch wahrscheinlich unter Inkrement / Dekrement konstant bleiben sollten.
Rawling 11.01.2013, 12:36
quelle
3

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.

%Vor%     
Eric Postpischil 11.01.2013 14:16
quelle

Tags und Links