2016-05-25 17 views
5

Ich habe ein Problem mit einer einfachen Multiplikation, die ich nicht verstehen kann ... Ich arbeite mit .Net Framework 4 und bauen in x86. Ich Ausführung den folgenden Code:Doppelte Multiplikation in C#

double x = 348333.673899683; 
double y = 4521014.98461396; 
double aux = x * y; 

Der erwartete Wert für aux ist 1574821759346,09949827752137468 (ich es mit einem einfachen Rechner getan haben). Der Wert, den ich in Aux erhalte, ist jedoch . Sehen Sie, das ist nicht ein Präzisionsfehler, auch die Integer Teil wurde geändert.

Wenn ich einen Haltepunkt in der Multiplikation setzen und die Maus über den Operator de * bewegen, sehe ich x * y = 1574821759346.0994 was ist ok. Wenn ich über den Aux-Variable schweben sehe ich aux = 1574821822464

Um den letzten Absatz zu klären, können zwei Bilder unten zu sehen:

enter image description here

enter image description here

Zuerst habe ich habe gedacht, dass ist vielleicht, weil die x86 compilation, aber den nächsten post lesen, verwerfe ich diese option:

The Double Byte Size in 32 bit and 64 bit OS

Ich kann nicht verstehen, was hier passiert. Jede Hilfe wird geschätzt.

--- EDIT MIT MEHR INFO ---

ich VS2015 verwende. Ich habe drei weitere Zeilen hinzugefügt, um es zu debuggen:

log.Info(x); 
log.Info(y); 
log.Info(aux); 

Um die Protokolle zu zeigen, dass ich die Bibliothek bin mit log4net. Die Ausgabe ist:

23322 [8] INFO Art.Model.Scenarios (null) - 348333,673899683 
24745 [8] INFO Art.Model.Scenarios (null) - 4521014,98461396 
26274 [8] INFO Art.Model.Scenarios (null) - 1574821822464 

So ist es kein Fehler im debuger. Wenn ich ein komplett neues Projekt und eine neue Lösung erstelle, funktioniert es gut, aber ich kann nicht verstehen, warum es in dieser Lösung nicht funktioniert.

--- ZWEITE EDIT ---

Dank der Kommentare, die ich etwas Neues versucht:

double x = 348333.673899683; 
double y = 4521014.98461396; 
double aux = x * y; 

decimal xx = 348333.673899683m; 
decimal yy = 4521014.98461396m; 
decimal auxx = xx * yy; 

log.Info(x); 
log.Info(y); 
log.Info(aux); 

log.Info(xx); 
log.Info(yy); 
log.Info(auxx); 

Und das Ergebnis ist:

16129 [8] INFO Art.Model.Scenarios (null) - 348333,673899683 
16145 [8] INFO Art.Model.Scenarios (null) - 4521014,98461396 
16145 [8] INFO Art.Model.Scenarios (null) - 1574821822464 
16145 [8] INFO Art.Model.Scenarios (null) - 348333,673899683 
16145 [8] INFO Art.Model.Scenarios (null) - 4521014,98461396 
16145 [8] INFO Art.Model.Scenarios (null) - 1574821759346,0994982775213747 

es So funktioniert mit der Dezimal, aber nicht mit der Doppel. Kann jemand das erklären? Ich kann nicht verstehen, warum passiert.

+4

Sind Sie sicher, dass es kein Debugger-Problem ist? Was sagt Console.WriteLine? Ich führe diesen Code in vs2015 C# interaktives Fenster und es gibt die richtige Antwort – pm100

+0

was vs Version? – pm100

+0

VS 2015 U2 Ausführung Fenster: 1574821759346.0994 – Dbl

Antwort

1

Am wahrscheinlichsten, falls Sie verwenden DirectX (der einzige Grund, warum ich hinter problematisch finden kann), ist dieses Problem auf die Tatsache, scheint, dass jedes Mal, wenn ein Gerät erzeugt und/oder verarbeitet, zwingt es die FPU in den Modus mit einfacher Genauigkeit, wodurch Genauigkeit verloren geht und doppelte, lange Dezimalvariablen abgeschnitten werden. Wenn ich einen IEEE-754 Fließkomma-Wandler versuche und Ihre Daten eintrage, bekomme ich dieses Ergebnis, was genau Ihr Fall ist: Ihre Daten wurden irgendwann als doppelt genaue Zahl gelesen, aber dann wurde sie in eine einzige abgeschnitten .precision Gleitkommazahl wie Sie sehen können:

enter image description here

Dieses Problem kann durch explizit den Aufbau der Geräte-Objekt unter der Flagge FpuPreserve gelöst werden.

Ich hatte auch dieses Problem, und am Anfang obwohl über falsche Casting oder so, bis nach einer langen Spur festgestellt, die Werte abgeschnitten wurde, nachdem ich ein DirectX Device-Objekt gebaut.

0

Das Phänomen tritt auf, wegen der Definition der Datentypen.

doppelt: "Präzision. Wenn Sie mit Gleitkommazahlen arbeiten, denken Sie daran, dass sie nicht immer eine genaue Darstellung im Gedächtnis haben „ https://msdn.microsoft.com/en-us//de/library/x99xtshc.aspx

dezimal:„. Im Vergleich zu Gleitkommatypen hat der Typ decimal mehr Präzision und eine kleinere Bereich, die es für angebracht, finanzielle und monetäre Berechnungen macht.“ https://msdn.microsoft.com/en-us//library/364x0z75.aspx

Doppel-Datentypen als Binärbruch gespeichert sind, aus diesem Grund können sie nicht genau dargestellt ist, wenn das kein Binärbruch ist. https://msdn.microsoft.com/en-us//ae382yt8