Un doppio davvero inadatto al denaro?

Dico sempre in c # una variabile di tipo double non adatta al denaro. Potrebbero accadere tutte le cose strane. Ma non riesco a creare un esempio per dimostrare alcuni di questi problemi. Qualcuno può fornire un esempio del genere?

(modifica: questo post era originariamente codificato in C #; alcune risposte si riferiscono a dettagli specifici del decimal , che quindi significa System.Decimal ).

(modifica 2: ero specifico per chiedere un codice c #, quindi non credo che questo sia solo un linguaggio indipendente)

Molto, molto inadatto. Usa decimale.

 double x = 3.65, y = 0.05, z = 3.7; Console.WriteLine((x + y) == z); // false 

(esempio dalla pagina di Jon qui – lettura consigliata ;-p)

Otterrete errori dispari effettivamente causati dall’arrotondamento. Inoltre, i confronti con i valori esatti sono estremamente difficili: di solito è necessario applicare una sorta di epsilon per verificare che il valore effettivo sia “vicino” a uno specifico.

Ecco un esempio concreto:

 using System; class Test { static void Main() { double x = 0.1; double y = x + x + x; Console.WriteLine(y == 0.3); // Prints False } } 

Sì, non è adatto.

Se ricordo bene, il doppio ha circa 17 numeri significativi, quindi normalmente gli errori di arrotondamento si verificano molto indietro rispetto al punto decimale. La maggior parte dei software finanziari utilizza 4 decimali dietro il punto decimale, il che lascia 13 decimali con cui lavorare, quindi il numero massimo con cui si può lavorare per le singole operazioni è ancora molto più alto del debito nazionale USA. Ma gli errori di arrotondamento si sumno nel tempo. Se il tuo software funziona per un lungo periodo, alla fine inizi a perdere centesimi. Alcune operazioni peggioreranno la situazione. Ad esempio, l’aggiunta di grandi quantità a piccole quantità causerà una significativa perdita di precisione.

Hai bisogno di dati fissi per le operazioni monetarie, alla maggior parte della gente non importa se perdi un centesimo qua e là ma i contabili non sono come la maggior parte delle persone ..

modificare
Secondo questo sito http://msdn.microsoft.com/en-us/library/678hzkk9.aspx, i doppi hanno in realtà da 15 a 16 cifre significative anziché 17.

@Jon Skeet decimale è più adatto del doppio a causa della sua maggiore precisione, 28 o 29 decimali significativi. Ciò significa meno possibilità che gli errori di arrotondamento accumulati diventino significativi. I tipi di dati a punti fissi (cioè gli interi che rappresentano i centesimi o il centesimo di un centesimo come quelli che ho visto usati) come le menzioni di Boojum sono in realtà più adatti.

Poiché decimal utilizza un fattore di ridimensionamento di multipli di 10, è ansible rappresentare esattamente numeri come 0.1. In sostanza, il tipo decimale rappresenta questo come 1/10 ^ 1, mentre un double rappresenterebbe questo come 104857/2 ^ 20 (in realtà sarebbe più simile al numero veramente grande / 2 ^ 1023).

Un decimal può rappresentare esattamente qualsiasi valore di base 10 con un massimo di 28/29 cifre significative (come 0,1). Un double non può.

La mia comprensione è che la maggior parte dei sistemi finanziari esprime la valuta usando i numeri interi, cioè contando tutto in centesimi.

La doppia precisione IEEE può effettivamente rappresentare tutti gli interi esattamente nell’intervallo da -2 ^ 53 a + 2 ^ 53. (Hacker’s Delight, pagina 262) Se si utilizzano solo addizione, sottrazione e moltiplicazione e si mantiene tutto in numeri interi all’interno di questo intervallo, non si dovrebbe notare alcuna perdita di precisione. Sarei molto diffidente nei confronti della divisione o di operazioni più complesse, comunque.

Usare il doppio quando non si sa cosa si sta facendo non è adatto.

“double” può rappresentare una quantità di trilioni di dollari con un errore di 1/90 ° di un centesimo. In questo modo otterrai risultati molto precisi. Vuoi calcolare quanto costa mettere un uomo su Marte e farlo tornare vivo? il doppio andrà bene.

Ma con i soldi ci sono spesso regole molto specifiche che dicono che un certo calcolo deve dare un certo risultato e nessun altro. Se si calcola un importo molto molto molto vicino a $ 98,135 allora ci sarà spesso una regola che determina se il risultato dovrebbe essere $ 98,14 o $ 98,13 e si deve seguire tale regola e ottenere il risultato richiesto.

A seconda di dove vivi, l’utilizzo di numeri interi a 64 bit per rappresentare centesimi o centesimi o copechi o qualsiasi altra unità più piccola del tuo paese funzionerà normalmente bene. Ad esempio, gli interi con segno a 64 bit che rappresentano i centesimi possono rappresentare valori fino a 92.223 trilioni di dollari. Gli interi a 32 bit di solito non sono adatti.

Nessun doppio avrà sempre errori di arrotondamento, usare “decimale” se sei su .Net …

In realtà il doppio punto a virgola mobile è perfettamente adatto a rappresentare somme di denaro finché si sceglie un’unità adeguata.

Vedi http://www.idinews.com/moneyRep.html

Quindi è a tempo determinato . O consuma 8 byte, sicuramente preferibile al 16 consumato da un elemento decimale .

Se qualcosa funziona (cioè produce il risultato atteso e corretto) non è una questione di voto o preferenza individuale. Una tecnica funziona o no.