Frage

Ich fahre einige Datentypkonvertierungen, wo ich brauche, um uint, long, ulong und decimal als IEEE 754 mit doppelten Gleitkomma-Werte darstellen. Ich möchte in der Lage sein zu erkennen, ob die IEEE 754-Datentyp nicht den Wert enthalten kann, bevor ich die Konvertierung durchführen.

Eine Brute-Force-Lösung wäre, einen Try-Catch um einen Guss zu wickeln für OverflowException zu verdoppeln suchen. Lesen durch bestimmte der CLR Dokumentation bedeutet, dass ohne Ausnahmen einige Umwandlungen nur stumm den Wert ändern.

Gibt es einen narrensicher Weg, um diese Überprüfung zu tun? Ich suche nach Vollständigkeit über eine einfache Implementierung. Ich habe das Gefühl, ich werde eng sein, um die IEEE 754-Spezifikation Lesen und Prüfen Matissa und Exponent sorgfältig ...

Ich sollte hinzufügen, dass ich die meisten betrifft repräsentieren ganze Zahlen genau und dass der Verlust von Gleitkommagenauigkeit ist von untergeordneter Bedeutung (aber immer noch eine Überlegung wert).

EDIT: Int32 der Lage ist, vollständig als IEE-754 ausgedrückt werden. Auch der Decimal Datentyp ist sehr viel Teil der Frage.

Wichtige Update: , wenn Sie auf diese Frage beziehen, sollten Sie auch diese Frage lesen: IEEE-754 Doppel (64-Bit-Gleitkomma) vs. Long (64-bit Integer) Revisited

Er stellt einen Fehler in der Antwort, wo einige sehr große Werte sind auch in der Lage genau nach IEEE-754 vertreten sein. Während dies bedeuten kann, dass der Wert korrekt Round-Trip, für meinen ursprünglichen Zweck (es wird Round-Trip zu JavaScript) wird es nicht.

Auch scheint es einen Fehler in der CLRs System.Double Typ zu sein, weil es nicht richtig, diese Werte zu Round-Trip zulässt.

War es hilfreich?

Lösung

Einfache Lösung könnte so etwas wie (, wenn x ein int ):

if ((int)(double)x != x) { 
  // won't convert
} else {
  // will convert
}

und so weiter für lange, etc.

(double) x wird x aus einem int zu einem Doppel konvertieren. Die (int) wandelt sie dann wieder zurück. So (int) (Doppel) x wandelt in einem doppelten ein int bilden, und dann zurück. Im Wesentlichen wird der Code überprüft, dass die Umwandlung ist reversibel zu verdoppeln (und damit, dass die Doppel des genauen Wert des int speichern können).

Andere Tipps

Dies hängt in erster Linie von der Anzahl Bereich, den Sie mit sind arbeitet. Solange Sie innerhalb von 15 Ziffern sind (für ein Doppel rel="nofollow), sollten Sie auf die sein sichere Seite für ganze Zahlen.

Im Grunde, was Sie brauchen, zu berücksichtigen, ist die Anzahl der signifikanten Stellen. Also, solange Sie Zahl kleiner als die signifikante Ziffer Grenze, wird es bleiben genau; wenn es größer wird, werden Sie Präzision verlieren (auch wenn diese ganzen Zahlen).

Also, solange Ihre Zahl ist <2 ^ 53, sind Sie in der Regel gut.

IEEE 754 Doppel haben 52 Bits für Mantisse und Sie konvertieren von / bis integer / long , so dass es ganz einfach zu testen. Wenn Sie Ihre ganze Zahl verbraucht weniger als 52 Bits, dann sollte es ohne Probleme zu IEEE 754 mit doppelter konvertierbar sein.

Ich gehe davon aus (Ich weiß sicher, im Fall von Java, aber nicht C # und faul, um zu überprüfen), dass int 32 Bit und 64 Bit lang. So sicher int kann in Doppel passen ohne Probleme sowohl Zeichen und unsign.

Für ulong Sie einfach, wenn alle Bits höher als das 52th Bit eins ist wie ((aULong && 0xFFF0000000000000) == 0).

Für lange haben Sie ihr Vorzeichen zu bringen, in der Betrachtung. Seit langer 2nd-Ergänzung ist aber IEEE754 nicht (haben nur negativ Bit), denke, es ist es nur verdeckte negativ lange positiv (* -1) und überprüfen, wie positive sicher ist. Also, wenn die lange negativ ist, Zeit mit -1 zuerst (nichts für positiv). Dann Prüfen Sie es wie ulong.

Hope, das hilft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top