2015-09-25 27 views
8

Ho letto in diversi post su stackoverflow e nella documentazione C#, che la conversione di long (o qualsiasi altro tipo di dati che rappresenta un numero) su double perde precisione. Questo è abbastanza ovvio a causa della rappresentazione di numeri in virgola mobile.Quanto è grande la conversione della perdita di precisione da lunga a doppia?

La mia domanda è: quanto è grande la perdita di precisione se converto un numero maggiore in double? Devo aspettarmi differenze maggiori di +/- X?

La ragione per cui vorrei sapere questo, è che devo occuparmi di un contatore continuo che è un long. Questo valore viene letto dalla mia domanda come string, deve essere lanciato e deve essere diviso per es. 10 o qualche altro piccolo numero e viene quindi elaborato ulteriormente.

Sarebbe più appropriato per questa attività decimal?

+0

Beh 'decimale' potrebbe certamente mantenere tutte le informazioni in un' lungo' ... ma non è davvero chiaro quali siano le vostre esigenze siamo. –

+0

@JonSkeet in realtà nessuno, so come risolverlo con i decimali, ma la domanda è più o meno per curiosità. Quanta perdita di precisione dovrei aspettarmi. – John

risposta

8

conversione long (o qualsiasi altro tipo di dati che rappresenta un numero) a double perde precisione. Questo è abbastanza ovvio a causa della rappresentazione di numeri in virgola mobile.

Questo è meno ovvio di quanto sembri, poiché la perdita di precisione dipende dal valore di long. Per i valori compresi tra -2 e 2 non esiste alcuna perdita di precisione.

Quanto è grande la perdita di precisione se si converte un numero maggiore in doppio? Devo aspettare differenze più grandi di +/- X

Per i numeri con magnitudo superiore al 2 si verificherà una perdita di precisione, a seconda di quanto sopra del limite di 52 bit si va.Se il valore assoluto di long si adatta, ad esempio, a 58 bit, l'entità della perdita di precisione sarà 58-52 = 6 bit o +/- 64.

decimal essere più appropriato per questa attività?

decimal ha una rappresentazione diversa da double e utilizza una base diversa. Dato che hai intenzione di dividere il tuo numero per "piccoli numeri", le diverse rappresentazioni ti darebbero diversi errori sulla divisione. Nello specifico, double sarà migliore nel gestire la divisione con le potenze di due (2, 4, 8, 16, ecc.) Perché tale divisione può essere eseguita sottraendo dall'esponente, senza toccare la mantissa. Allo stesso modo, large decimal s non subirebbe perdite di cifre significative se diviso per dieci, cento, ecc.

+0

Perfetto! Pensavo che questo calcolo mi avrebbe dato la perdita di precisione ma non ero sicuro. La perdita è in realtà più piccola di quanto mi sarei aspettato. Grazie! – John

3

long

long è un tipo integer a 64 bit e possono contenere valori da -9.223.372.036.854.775.808 a 9,223,372,036,854,775,807 (max. 19 cifre).

double

double è di tipo in virgola mobile a 64 bit con precisione da 15 a 16 cifre. Quindi i dati possono essere persi nel caso in cui i numeri siano superiori a ~ 100.000.000.000.000.

decimal

decimal è un tipo decimale 128 bit e può contenere fino a 28-29 cifre. Quindi è sempre sicuro trasmettere long a decimal.

Raccomandazione

vorrei consigli che scoprire le esatte aspettative circa i numeri che dovrà lavorare con. Quindi puoi prendere una decisione informata nella scelta del tipo di dati appropriato. Dal momento che stai leggendo i tuoi numeri da una stringa, non è possibile che saranno ancora più grandi di 28 cifre? In tal caso, nessuno dei tipi elencati funzionerà per te e dovrai invece utilizzare una sorta di implementazione BigInt.

+0

È certo che non supererà l'intervallo di lungo. Grazie per la risposta! – John