Betrachten Sie das folgende C# -Code hinzu:Warum wirkt sich die um die Rundung, wenn mehrere Doppel in C#
double result1 = 1.0 + 1.1 + 1.2;
double result2 = 1.2 + 1.0 + 1.1;
if (result1 == result2)
{
...
}
result1 sollte immer gleich result2 richtig? Die Sache ist, es tut es nicht. result1 ist 3.3 und result2 ist 3.3000000000000003. Der einzige Unterschied ist die Reihenfolge der Konstanten.
Ich weiß, dass Doppelgänger so implementiert sind, dass Rundungsprobleme auftreten können. Ich bin mir bewusst, dass ich stattdessen Dezimalzahlen verwenden kann, wenn ich absolute Präzision brauche. Oder dass ich Math.Round() in meiner if-Anweisung verwenden kann. Ich bin nur ein Nerd, der verstehen will, was der C# -Compiler tut. Kann mir das jemand sagen?
Edit:
Dank an alle, die bisher vorgeschlagenen auf Gleitkomma-Arithmetik zu lesen und/oder sprachen über die inhärente Ungenauigkeit, wie die CPU verdoppelt abwickelt. Aber ich glaube, der Hauptstoß meiner Frage ist noch immer unbeantwortet. Was ist meine Schuld, weil ich es nicht richtig formuliert habe? Lassen Sie es mich so sagen:
Brechen Sie den obigen Code nach unten, würde ich die folgenden Operationen erwarten zu geschehen: Die
double r1 = 1.1 + 1.2;
double r2 = 1.0 + r1
double r3 = 1.0 + 1.1
double r4 = 1.2 + r3
Nehmen wir an, dass jeder der oben genannten Ergänzungen einen Rundungsfehler (nummeriert e1 hatte. .e4). So enthält r1 den Rundungsfehler e1, r2 enthält Rundungsfehler e1 + e2, r3 enthält e3 und r4 enthält e3 + e4.
Nun weiß ich nicht, wie genau die Rundungsfehler passieren, aber ich hätte erwartet, dass e1 + e2 gleich e3 + e4 ist. Natürlich nicht, aber das scheint mir irgendwie falsch zu sein. Eine andere Sache ist, dass wenn ich den obigen Code ausführen, bekomme ich keine Rundungsfehler. Das ist es, was mich denken lässt, dass es der C# -Compiler ist, der eher etwas Seltsames macht als die CPU.
Ich weiß, ich frage viel und vielleicht die beste Antwort, die jemand geben kann, ist zu gehen und einen PHD in CPU-Design zu tun, aber ich dachte nur, ich würde fragen.
Edit 2
am IL Blick von meinem ursprünglichen Code-Beispiel, dann ist es klar, dass es der Compiler ist nicht die CPU, die dies tut:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] float64 result1,
[1] float64 result2)
L_0000: nop
L_0001: ldc.r8 3.3
L_000a: stloc.0
L_000b: ldc.r8 3.3000000000000003
L_0014: stloc.1
L_0015: ret
}
Der Compiler fügt die Zahlen nach oben für mich!
+1 gutes konkretes Beispiel – bobince
Das Beispiel ist gut, aber Sie haben die Reihenfolge der Operationen im Vergleich zum ursprünglichen Code geändert. Das OP hat das gleiche beim ersten Schnitt gemacht. –