Mantisse und Exponent in Doppel konvertieren

8

In einer sehr leistungsfähigen App finden wir, dass die CPU lange Arithmetik deutlich schneller berechnen kann als mit Doppel. In unserem System wurde jedoch festgestellt, dass wir nie mehr als 9 Dezimalstellen Genauigkeit benötigen. Also verwenden wir Longs für alle Gleitkomma-Arithmetik mit einer Genauigkeit von 9 Punkten verstanden.

In bestimmten Teilen des Systems ist es jedoch aufgrund der Lesbarkeit bequemer, mit Doppel zu arbeiten. Also müssen wir zwischen dem langen Wert, der 9 Dezimalstellen voraussetzt, in ein Doppel konvertieren.

Wir finden, dass das einfache Nehmen der langen und Teilen durch 10 zur Macht von 9 oder das Multiplizieren mit 1 geteilt durch 10 zur Macht von 9 ungenaue Darstellungen in einem Doppel gibt.

Um das zu lösen, verwenden wir Math.Round(value,9) , um die genauen Werte anzugeben.

Allerdings ist Math.Round() für die Leistung entsetzlich langsam.

Unsere Idee im Moment ist also, die Mantisse und den Exponenten direkt in das binäre Format eines Doppelpunkts zu konvertieren, da dann keine Rundung mehr nötig ist.

Wir haben online gelernt, wie man Bits eines Doppels untersucht, um die Mantisse und den Exponenten zu erhalten, aber es ist verwirrend herauszufinden, wie man das umkehrt, um eine Mantisse und einen Exponenten zu nehmen und ein Doppel zu machen, indem man die Bits verwendet.

Irgendwelche Vorschläge?

%Vor%     
Wayne 19.01.2012, 13:26
quelle

2 Antworten

1

Sie sollten keinen Skalierungsfaktor von 10 ^ 9 verwenden, stattdessen sollten Sie 2 ^ 30 verwenden.

    
erikkallen 19.01.2012 13:43
quelle
0

Wie Sie bereits anhand der anderen Antwort erkannt haben, funktionieren Double-Operationen mit binären Fließkommazahlen und nicht mit Fließkomma-Dezimalzahlen. Daher funktioniert die ursprüngliche Methode nicht.

Es ist auch nicht klar, ob es mit einer absichtlich vereinfachten Formel arbeiten könnte, weil es nicht klar ist, was die maximale Reichweite ist, die man braucht, damit eine Rundung unvermeidlich wird.

Das Problem, dies schnell, aber genau zu tun, ist gut untersucht und wird oft von CPU-Anweisungen unterstützt. Ihre einzige Chance, die integrierten Conversions zu übertreffen, ist entweder:

  1. Sie haben einen mathematischen Durchbruch erzielt, der es wert ist, dass einige ernsthafte Artikel darüber geschrieben werden.
  2. Sie schließen genügend Fälle aus, die in Ihren eigenen Beispielen nicht vorkommen werden, obwohl die eingebauten besser sind und Ihre eigene für Sie optimiert ist.

Wenn der Wertebereich, den Sie verwenden, sehr begrenzt ist, wird das Potenzial für die Konvertierung zwischen Double-Precision IEEE 754 und Long Integer immer kleiner.

Wenn Sie an dem Punkt sind, an dem Sie die meisten Fälle von IEEE 754 abdecken müssen, oder sogar einen beträchtlichen Teil davon, dann werden Sie die Dinge langsamer machen.

Ich würde empfehlen, entweder bei dem zu bleiben, was Sie haben, die Fälle zu verschieben, in denen double bequemer ist, trotz der Unannehmlichkeiten trotzdem lange zu bleiben, oder wenn Sie decimal verwenden. Sie können ein decimal von einem long einfach mit:

erstellen %Vor%

Nun ist decimal in arithmetischen Größenordnungen langsamer als double (gerade weil es einen ähnlichen Ansatz wie Sie in der Anfangsfrage implementiert, aber mit einem variierenden Exponenten und einer größeren Mantisse). Aber wenn Sie nur einen einfachen Weg brauchen, um einen Wert für die Darstellung oder das Rendern als String zu erhalten, hat das Hand-Hacken der Konvertierung in decimal Vorteile gegenüber dem Hand-Hacken der Konvertierung in double , also könnte lohnt sich anzuschauen.

    
Jon Hanna 19.01.2012 15:27
quelle