2013-10-17 14 views
7

Wenn ich den folgenden Ausdruck:Implizite Konvertierung/Förderung von float oder double in Ausdrücken zwischen C# und Java

byte A = 69; 
int B = 123; 
long C =; 
float D = 4.9f; 
double E = 11.11; 

double X = (B * 100) + 338.1 - (E/B)/C; 
double X1 = (B * 100) + (A * D) - (E/B)/C; 

// JAVA - lost precision 
System.out.println(X); // 12638.099971861307 
System.out.println(X1); // 12638.099581236307 

// C# - almost the same 
Console.WriteLine(X); // 12638.0999718613 
Console.WriteLine(X1) // 12638.0999784417 

Ich bemerkte, dass Java verliert Präzision von X, wobei 338,1 implizite doppelt so hoch ist, während C# macht fast nicht . Ich verstehe nicht warum, denn 338.1 ist gleich float und double. Nach dem Punkt gibt es nur eine Ziffer.

+1

338.1 ist nicht identisch in float und double. Die exakte binäre Expansion von 338.1 wiederholt sich für immer, also wenn sie als ein Doppelwort ausgedrückt wird, hat sie eine ganze Menge mehr Nicht-Null-Stellen als wenn sie als Float ausgedrückt wird. –

+1

lesen Sie bitte http://csharpindepth.com/Articles/General/FloatingPoint.aspx – Rohit

Antwort

1

In Java wird (B * 100) + (A * D) ein Float sein; und es wird der Float sein, der 12638.1 am nächsten ist. 12638 benötigt jedoch 14 Ziffern, um in binär auszudrücken, einschließlich der ersten 1; was 10 Ziffern des Signifikanten übrig lässt, um den Bruchteil auszudrücken. Daher werden Sie die nächste Zahl von 1024stel bis 0,1 erhalten - das ist 102/1024. Das ergibt 0,099609375 - also hat der Float einen Rundungsfehler von 0,000390625.

Das scheint der Unterschied zwischen X und X1 zu sein, den Sie in Ihrem Java-Programm bekommen.

Ich fürchte, ich bin kein C# -Experte, daher kann ich Ihnen nicht sagen, warum C# anders ist.

0

Dies hat mit der Compiler Interpretation Ihres Ausdrucks zu tun. Da Sie keine Zwischentypenumwandlungen angegeben haben, führt der Compiler die Konvertierung A * D als erste Typumwandlung und dann Multiplikation durch, anstatt die Umkehrung, die Sie erwarten würden. Dies mag wie ein seltsames Ergebnis erscheinen, aber es ist eine Möglichkeit für den Compiler, Ihnen ein exakteres Ergebnis zu geben, ohne dass Sie lästige Typumwandlungen angeben müssen.

Java behandelt nicht das für Sie, und so (B * 100) + (A * D) ist die Multiplikation eines int und einem float - was zu einem float. Dies kann in C# wie folgt simuliert werden:

double X2 = (float)((B * 100) + (A * D)) - (E/B)/C; 
Console.WriteLine("X2: {0}", X2); 

Dies ist einer der Vorteile (oder Dis-Vorteile einig wohl sagen würde) ein High-Level-Compiler.

Verwandte Themen