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%Sie sollten keinen Skalierungsfaktor von 10 ^ 9 verwenden, stattdessen sollten Sie 2 ^ 30 verwenden.
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:
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:
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.
Tags und Links c# floating-point double exponent mantissa