Domanda

Dico sempre in c # che una variabile di tipo double non è adatta per soldi. Tutte le cose strane potrebbero accadere. Ma non riesco a creare un esempio per dimostrare alcuni di questi problemi. Qualcuno può fornire un esempio del genere?

(modifica; questo post è stato originariamente taggato C #; alcune risposte si riferiscono a dettagli specifici di decimale , che quindi significa System.Decimal ).

(modifica 2: stavo specificatamente chiedendo un po 'di codice c #, quindi non credo che questo sia solo un linguaggio agnostico)

È stato utile?

Soluzione

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)

Altri suggerimenti

Riceverai strani errori causati effettivamente dall'arrotondamento. Inoltre, i confronti con valori esatti sono estremamente complicati: di solito è necessario applicare una sorta di epsilon per verificare che il valore effettivo sia "vicino". uno particolare.

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 che il doppio ha circa 17 numeri significativi, quindi normalmente gli errori di arrotondamento avranno luogo molto indietro rispetto al punto decimale. La maggior parte dei software finanziari utilizza 4 decimali dietro il punto decimale, lasciando 13 decimali con cui lavorare, quindi il numero massimo con cui è possibile lavorare per singole operazioni è ancora molto più elevato del debito nazionale degli Stati Uniti. Ma gli errori di arrotondamento si sommeranno nel tempo. Se il tuo software funziona a lungo, alla fine inizierai a perdere centesimi. Alcune operazioni peggioreranno la situazione. Ad esempio, l'aggiunta di grandi quantità a piccole quantità comporterà una perdita significativa di precisione.

Hai bisogno di tipi di dati a virgola fissa per operazioni di denaro, alla maggior parte delle persone non importa se perdi un centesimo qua e là ma i contabili non sono come la maggior parte delle persone ..

modifica
Secondo questo sito http://msdn.microsoft.com/en-us/library /678hzkk9.aspx I doppi hanno in realtà da 15 a 16 cifre significative invece di 17.

Il decimale @Jon Skeet è più adatto del doppio a causa della sua maggiore precisione, 28 o 29 decimali significativi. Ciò significa che le minori probabilità che errori di arrotondamento accumulati diventino significativi. I tipi di dati a virgola fissa (ovvero numeri interi che rappresentano centesimi o il centesimo di centesimo come ho visto usato) come le menzioni di Boojum sono in realtà più adatti.

Poiché decimale utilizza un fattore di ridimensionamento di multipli di 10, numeri come 0,1 possono essere rappresentati esattamente. In sostanza, il tipo decimale rappresenta questo come 1/10 ^ 1, mentre un double lo rappresenterebbe come 104857/2 ^ 20 (in realtà sarebbe più simile a davvero-grande-numero / 2 ^ 1023).

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

La mia comprensione è che la maggior parte dei sistemi finanziari esprime valuta utilizzando numeri interi, vale a dire contando tutto in centesimi.

La doppia precisione IEEE in realtà può rappresentare tutti gli interi esattamente nell'intervallo compreso tra -2 ^ 53 e + 2 ^ 53. (Hacker's Delight, p. 262) Se usi solo addizione, sottrazione e moltiplicazione e mantieni tutto a valori integri in questo intervallo, non dovresti vedere alcuna perdita di precisione. Starei molto attento alla divisione o alle operazioni più complesse, tuttavia.

L'uso del doppio quando non sai cosa stai facendo non è adatto.

" doppia " può rappresentare un importo di un trilione di dollari con un errore di 1/90 di centesimo. In questo modo otterrai risultati estremamente precisi. Vuoi calcolare quanto costa rimettere un uomo su Marte e riportarlo in vita? il doppio andrà bene.

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

A seconda di dove vivi, usare numeri interi a 64 bit per rappresentare centesimi o centesimi o copechi o qualunque sia l'unità più piccola nel tuo paese funzionerà normalmente bene. Ad esempio, numeri interi con segno a 64 bit che rappresentano centesimi possono rappresentare valori fino a 92.223 trilioni di dollari. I numeri interi a 32 bit non sono generalmente adatti.

Nessun doppio avrà sempre errori di arrotondamento, utilizzare "decimale" se sei su .Net ...

In realtà a virgola mobile doppio è perfettamente adatto a rappresentare somme di denaro purché si scelga un'unità adatta.

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

Quindi è a virgola fissa lungo . O consuma 8 byte, sicuramente preferibile ai 16 consumati da un elemento decimale .

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top