Sie scheinen die Vorteile der Verwendung eines Gleitkommatyps genau zu kennen. Ich neige in allen Fällen dazu, für Dezimalstellen zu entwerfen, und verlasse mich auf einen Profiler, der mich darüber informiert, ob Operationen mit Dezimalstellen Engpässe oder Verlangsamungen verursachen. In diesen Fällen werde ich "down cast", um zu verdoppeln oder zu schweben, aber nur intern, und sorgfältig versuchen, den Präzisionsverlust zu verwalten, indem ich die Anzahl der signifikanten Stellen in der ausgeführten mathematischen Operation beschränke.
Wenn Ihr Wert vorübergehend ist (nicht wiederverwendet wird), können Sie im Allgemeinen einen Gleitkommatyp verwenden. Das eigentliche Problem bei Gleitkommatypen sind die folgenden drei Szenarien.
- Sie aggregieren Gleitkommawerte (in diesem Fall setzen sich die Genauigkeitsfehler zusammen).
- Sie erstellen Werte basierend auf dem Gleitkommawert (z. B. in einem rekursiven Algorithmus).
- Sie rechnen mit einer sehr großen Anzahl von signifikanten Stellen (zum Beispiel
123456789.1 * .000000000000000987654321
)
BEARBEITEN
Gemäß der Referenzdokumentation zu C # -Dezimalzahlen :
Das Dezimalschlüsselwort bezeichnet einen 128-Bit-Datentyp. Im Vergleich zu Gleitkommatypen weist der Dezimaltyp eine größere Genauigkeit und einen kleineren Bereich auf, wodurch er für finanzielle und monetäre Berechnungen geeignet ist.
Um meine obige Aussage zu verdeutlichen:
Ich neige in allen Fällen dazu, für Dezimalstellen zu entwerfen, und verlasse mich auf einen Profiler, der mich darüber informiert, ob Operationen mit Dezimalstellen Engpässe oder Verlangsamungen verursachen.
Ich habe immer nur in Branchen gearbeitet, in denen Dezimalstellen günstig sind. Wenn Sie an Phsyics- oder Grafik-Engines arbeiten, ist es wahrscheinlich viel vorteilhafter, für einen Gleitkommatyp (Float oder Double) zu entwerfen.
Dezimal ist nicht unendlich genau (es ist unmöglich, unendliche Genauigkeit für Nicht-Integral in einem primitiven Datentyp darzustellen), aber es ist weitaus genauer als doppelt:
- Dezimal = 28-29 signifikante Stellen
- double = 15-16 signifikante Stellen
- float = 7 signifikante Stellen
BEARBEITEN 2
Als Antwort auf den Kommentar von Konrad Rudolph ist Punkt 1 (oben) definitiv richtig. Die Aggregation von Ungenauigkeiten verstärkt sich tatsächlich. Ein Beispiel finden Sie im folgenden Code:
private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;
public static void Main(string[] args)
{
Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
float asSingle = 0f;
double asDouble = 0d;
decimal asDecimal = 0M;
for (int i = 0; i < ONE_MILLION; i++)
{
asSingle += THREE_FIFTHS;
asDouble += THREE_FIFTHS;
asDecimal += (decimal) THREE_FIFTHS;
}
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
Console.ReadLine();
}
Dies gibt Folgendes aus:
Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000
Wie Sie sehen können, sind die Ergebnisse des Doppelten weniger genau (obwohl sie wahrscheinlich korrekt gerundet werden), obwohl wir aus derselben Quellenkonstante addieren, und der Float ist weitaus ungenauer, bis zu dem Punkt, an dem er nur auf reduziert wurde zwei signifikante Ziffern.