2015-05-27 11 views
8

Wenn JavaScript-Nummer und C# -Doppel gleich spezifiziert sind (IEEE 754), warum werden Zahlen mit vielen signifikanten Ziffern anders behandelt?Warum werden Zahlen mit vielen signifikanten Stellen in C# und JavaScript anders behandelt?

var x = (long)1234123412341234123.0; // 1234123412341234176 - C# 
var x =  1234123412341234123.0; // 1234123412341234200 - JavaScript 

Ich bin nicht mit der Tatsache besorgt, dass IEEE 754 nicht die Zahl darstellen kann 1234123412341234123. ich mit der Tatsache, bin besorgt, dass die beiden Implementierungen nicht das gleiche für Zahlen handeln, die nicht mit voller Genauigkeit dargestellt werden.

sein Dies kann, weil IEEE 754 unter angegeben ist, eine oder beiden Implementierungen fehlerhaft sind oder dass sie verschiedene Varianten von IEEE implementieren 754.

Dieses Problem zu Problemen ist nicht im Zusammenhang mit Punkt Ausgabe in C# Formatierung schweben. Ich gebe 64-Bit-Ganzzahlen aus. Beachten Sie Folgendes:

long x = 1234123412341234123; Console.WriteLine(x); // Prints 1234123412341234123 double y = 1234123412341234123; x = Convert.ToInt64(y); Console.WriteLine(x); // Prints 1234123412341234176

Die gleiche Variable druckt verschiedene Saiten, da die Werte unterschiedlich sind.

+0

Warum bist du zu lang? –

+0

Sie vergleichen ein Doppel mit einem Float, denke ich. Wenn Sie in der Lage sein möchten, mit großen Zahlen zu rechnen, empfehle ich Ihnen, http://mikemcl.github.io/decimal.js/ zu verwenden und String-Nummern anzugeben, um die Anzahl der gewünschten Ziffern zu erhalten. Dies beantwortet Ihre Frage nicht, könnte aber ein wenig helfen, wenn Sie ein Problem haben. Große Zahlen werden normalerweise als Formelwert gespeichert und dadurch können Rundungsfehler auftreten. Deshalb sind Gleitkommawerte nicht präzise. Sie könnten in eine große Anzahl von Ungenauigkeiten in Javascript gestolpert haben. Zum Grund vielleicht schauen Sie in https://code.google.com/p/v8/ – Tschallacka

+0

Es gibt ein anderes interessantes Problem hier ... Das .NET zeigt normalerweise nur 15 Stellen der Präzision, anstelle der vollen 17. – xanatos

Antwort

3

Es gibt mehrere Probleme hier ...

Sie verwenden long statt double.

double x = 1234123412341234123.0; 

oder

var x = 1234123412341234123.0; 

Das andere Problem ist, dass .NET rundet double s bis 15 Stellen, bevor es zu string (so vor zum Beispiel das Drucken mit Console.ToString()) Umwandlung: Sie würde schreiben müssen.

Zum Beispiel:

string str = x.ToString("f"); // 1234123412341230000.00 

Siehe zum Beispiel https://stackoverflow.com/a/1658420/613130

Intern wird die Zahl ist immer noch mit 17 Ziffern, nur wird gezeigt, mit 15

Sie können es sehen, wenn Sie ein tun :

string str2 = x.ToString("r"); // 1.2341234123412342E+18 
2

Die Zahlen werden nicht anders behandelt, sie sind wird nur anders angezeigt.

.NET zeigt die Nummer mit 15 signifikanten Ziffern an, während JavaScript sie mit 17 signifikanten Ziffern anzeigt. Die Darstellung eines Double kann 15-17 signifikante Ziffern enthalten, je nachdem, welche Zahl es enthält. In .NET wird nur die Anzahl der Ziffern angezeigt, die die Zahl immer unterstützt, während JavaScript alle Ziffern anzeigt, die Genauigkeitsbegrenzung jedoch möglicherweise angezeigt wird.

.NET verwendet die wissenschaftliche Notation, wenn der Exponent 15 ist, und JavaScript verwendet sie, wenn der Exponent 21 ist. Das bedeutet, dass JavaScript Zahlen mit 18 bis 20 Ziffern anzeigt, die am Ende mit Nullen aufgefüllt werden.

Die Umwandlung der double in eine long in Ihrem Beispiel wird umgehen, wie .NET verdoppelt anzeigt. Die Zahl wird ohne die Rundung konvertiert, die die Genauigkeitsbegrenzung verbirgt. In diesem Fall sehen Sie den tatsächlichen Wert, der sich im Double befindet.Der Grund dafür, dass es nicht nur Nullen jenseits der 17. Ziffer gibt, ist, dass der Wert in binärer Form gespeichert wird, nicht in dezimaler Form.

1

Haftungsausschluss: Diese basieren, die Standards wikipedia page

Nach der Wikipedia-Seite für den Standard definiert, dass ein decimal64 16-stelliger Genauigkeit haben sollte.

Vorbei ist es die Entscheidung des Herstellers, was mit den zusätzlichen Ziffern gemacht werden sollte.

Sie können also sagen, dass der Standard unterspezifiziert ist, aber diese Zahlen sind nicht so ausgelegt, dass sie trotzdem in die Normenspezifikationen passen. In beiden Sprachen gibt es Möglichkeiten, mit größeren Zahlen umzugehen, daher sind diese Optionen möglicherweise besser für Sie geeignet.

+0

Die 16-stellige Genauigkeit, die vorgeschrieben wird, scheint zu bedeuten, dass .NET und Chrome gebrochen sind, da die Nummer 9111234123412341 in beiden Implementierungen zu 9111234123412340 geändert wird. –

+0

@HansMalherbe - Aber Sie beurteilen dies anhand ihrer String-Repräsentation und nicht anhand der tatsächlichen Zahl (In C# werden sie mindestens in [15 sf] angezeigt) (http://stackoverflow.com/a/1658420/1324033)) – Sayse

Verwandte Themen