2015-05-27 2 views
8

Se il numero di codice JavaScript e il numero doppio di C# sono specificati allo stesso modo (IEEE 754), perché i numeri con molte cifre significative vengono gestiti in modo diverso?Perché i numeri con molte cifre significative sono gestiti in modo diverso in C# e JavaScript?

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

Non mi interessa il fatto che IEEE 754 non può rappresentare il numero 1234123412341234123. Mi preoccupa il fatto che le due implementazioni non agiscono lo stesso per i numeri che non possono essere rappresentati con precisione completa.

Ciò può essere dovuto al fatto IEEE 754 è sotto specificato, una o entrambe le implementazioni sono guasti o che prevedano l'impiego di diverse varianti di IEEE 754.

Questo problema non è correlato a problemi con floating point uscita formattazione in C#. Sto emettendo numeri interi a 64 bit. Si consideri il seguente:

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

Le stesse stampe variabili diverse stringhe perché i valori sono diversi.

+0

Perché lanci a lungo? –

+0

Si sta confrontando un doppio con un float, penso. se vuoi essere in grado di calcolare con grandi numeri ti consiglio di usare http://mikemcl.github.io/decimal.js/ e di fornire numeri di tipo stringa per ottenere il numero di cifre che desideri. Questo non risponde alla tua domanda, ma potrebbe aiutare un po 'se stai affrontando un problema. I grandi numeri di solito vengono salvati come valore di formula e gli errori di arrotondamento possono verificarsi a causa di ciò. Ecco perché i punti fluttuanti non sono precisi. Potresti esserti imbattuto in una grande imprecisione di arrotondamento in javascript. Per quanto riguarda la ragione, forse guarda https://code.google.com/p/v8/ – Tschallacka

+0

C'è un altro problema interessante qui ... .NET normalmente mostra solo 15 cifre di precisione, invece del pieno 17. – xanatos

risposta

3

ci sono più problemi qui ...

si utilizza long invece di double. Si avrebbe bisogno di scrivere:

double x = 1234123412341234123.0; 

o

var x = 1234123412341234123.0; 

L'altro problema è che .NET arrotonda double s a 15 cifre prima di convertirlo in string (quindi prima ad esempio la stampa con Console.ToString()).

Ad esempio:

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

veda ad esempio https://stackoverflow.com/a/1658420/613130

Internamente il numero è ancora con 17 cifre, solo che viene mostrato con 15.

Lo si può vedere se si fa un :

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

I numeri non vengono gestiti in modo diverso, sono solo visualizzato diversamente.

.NET visualizza il numero con 15 cifre significative, mentre JavaScript lo visualizza con 17 cifre significative. La rappresentazione di un doppio può contenere 15-17 cifre significative, a seconda del numero che contiene. .NET mostra solo il numero di cifre che il numero è garantito per supportare sempre, mentre JavaScript mostra tutte le cifre ma potrebbe apparire la limitazione di precisione.

.NET inizia a utilizzare la notazione scientifica quando l'esponente è 15, mentre JavaScript inizia a utilizzarlo quando l'esponente è 21. Ciò significa che JavaScript visualizzerà numeri con da 18 a 20 cifre riempiti con zeri alla fine.

La conversione di double in un long nel tuo esempio eluderà il modo in cui .NET visualizza il doppio. Il numero verrà convertito senza l'arrotondamento che nasconde la limitazione di precisione, quindi in questo caso viene visualizzato il valore effettivo nel doppio.La ragione per cui non ci sono solo zero oltre la diciassettesima cifra è che il valore è memorizzato in forma binaria, non in forma decimale.

1

responsabilità: questo è basato fuori gli standard wikipedia page

Secondo la pagina di wikipedia per lo standard, si definisce che una decimal64 dovrebbe avere 16 cifre di precisione.

Passato che è la decisione implementatori su ciò che dovrebbe essere fatto con le cifre aggiuntive.

Quindi si può dire che lo standard è sottodescritto, ma in ogni caso questi numeri non sono progettati per adattarsi alle specifiche degli standard. Entrambe le lingue hanno modi per gestire numeri più grandi, quindi queste opzioni potrebbero essere più adatte a te.

+0

La precisione di 16 cifre che viene richiesta sembra implicare sia .NET che Chrome perché il numero 9111234123412341 viene modificato in 9111234123412340 in entrambe le implementazioni. –

+0

@HansMalherbe - Ma stai giudicando questo in base alla loro rappresentazione di stringa piuttosto che al numero effettivo (in C# almeno vengono visualizzati in [15 sf] (http://stackoverflow.com/a/1658420/1324033)) – Sayse