2016-10-18 5 views
1

Ich bin gespannt, ob Sie decimal in double konvertieren könnten, aber immer noch in der Lage sein, wieder zu demselben decimal ich begann mit. Natürlich unter der Annahme, dass Sie 15 oder weniger signifikante Ziffern verwenden. Grundsätzlich können, zählen Sie dazu:Reversible Dezimal zu Doppelkonvertierung

decimal original = someValue; 
double converted = ReversibleToDouble(original); 
decimal result = BackToDecimal(converted); 
if (original == result) 
    Console.WriteLine("All is well with the world."); 

ich nichts dagegen, wenn ReversibleToDouble eine Ausnahme oder etwas geworfen, wenn es keine solche Umwandlung ist, solange das Ergebnis nach erfolgreichem Abschluss gewährleistet ist. Gerade jetzt, das ist die triviale Lösung Ich habe:

public static double ReversibleToDouble(decimal input) 
{ 
    double output = (double)input; 

    if ((decimal)output != input) 
     throw new ArgumentException("Impossible to convert reversibly.", "input"); 

    return output; 
} 

public static decimal BackToDecimal(double input) 
{ 
    return (decimal)input; 
} 

Ich weiß nicht wirklich viel über numerische Analyse wissen, damit ich ein paar Fragen zu diesem.

Erste Frage: Ist diese triviale Methode garantiert ohne Ausnahme zu arbeiten , wenn es weniger als 15 signifikante Ziffern vor dem Versuch, Konvertierungen zu versuchen?

Wenn nicht, zweite Frage: Gibt es eine Möglichkeit, dies mit größerer Wahrscheinlichkeit zu arbeiten?

Wenn ja, eine letzte Frage: Ist das machbar, ohne ein Fachgebiet zu studieren? :)

+2

Ich denke, das ist eine gute Frage (numerische Analyse ist hart), aber ich verstehe nicht, warum es in Ordnung wäre, Informationen aus dem 'zu verlieren Dezimal "durch Runden, aber nicht OK, um es zu verlieren, indem man eine naive Umwandlung zu' doppeltem 'durchführt. –

+1

@MichaelBurr Guter Punkt. Ich habe diesen Teil tatsächlich hinzugefügt, weil ich weiß, dass Doppelgänger eine eingeschränkte Präzision haben, aber in Wirklichkeit werde ich nicht wirklich mit so vielen Ziffern arbeiten. Grundsätzlich interessiere ich mich mehr für die Eigenschaften dieser Conversions und ob ich dieser Gleichheitsprüfung für relativ "einfache" Zahlen vertrauen kann, die in binärer Darstellung schlecht aussehen könnten. Es ist völlig richtig, dass ich dieses Problem umgehen kann, ich frage mich nur, ob das Problem überhaupt existiert. Wenn das Sinn macht. –

+0

Darf ich fragen, warum Sie das brauchen? – Paparazzi

Antwort

0

Sie können nicht.

Dezimal ist ein 128-Bit-Typ, Doppel eine 64-Bit-Typ ist, so dass Sie gehen Informationen zu verlieren, wenn das Konvertieren von Dezimal

+0

Deshalb habe ich gefragt, ob es funktionieren würde, wenn ich die Dezimalstelle auf 15 signifikante Ziffern gerundet hätte, sonst nicht. Ich werde betonen. –

0

zu verdoppeln Was Sie verlangen, ist die kürzeste Dezimalwert wie zu finden, die abgerundet werden würde zu demselben Schwimmer.

Das ist genau der Algorithmus verwendet, um eine Floating-Point-in-Schema zu drucken, Java, Python, Squeak/Pharo Smalltalk, etc ...

Die Antwort ist also ja, wir können in der Regel, solange es aren‘ t zu viele Dezimalstellen. Jetzt frage nicht den Unterschied zwischen allgemein und immer, ich bin mir nicht sicher, ob ich das leicht beantworten kann.

In Pharo Smalltalk würden Sie die Nachricht asMinimalDecimalFraction verwenden, um die Aufgabe zu erledigen. https://github.com/pharo-project/pharo-core/blob/6.0/Kernel.package/Float.class/instance/printing/asMinimalDecimalFraction.st

A Fraction in Smalltalk ist nicht gerade ein Dezimal in C#, da es mit beliebiger Genauigkeit und willkürliche Nenner hat, aber einige Grundsätze gelten oben für beide.

Siehe auch

Count number of digits after `.` in floating point numbers?

Convert float to rounded decimal equivalent