Discussione:
Sottrazione tra numeri double
(troppo vecchio per rispondere)
Andrea
2007-07-26 10:16:32 UTC
Permalink
Salve a tutti,
ho notato che facedno una banalissima sottrazione tra due double il
risultato non è del tutto corretto.
Es.

double a = 2.05;
double b = 3.02;
double c = b - a;

Se si va a vedere c, viene 0.9700000000000002.
Perchè?
VITRIOL
2007-07-26 10:33:50 UTC
Permalink
Post by Andrea
double a = 2.05;
double b = 3.02;
double c = b - a;
Sinceramente a me, nel caso specifico, sembra che non succede:

Loading Image...

Però, in linea generale, devi tenere conto che quando usi numeri in
virgola la mobile dietro l'angolo hai sempre la possibilità di un errore
di approssimazione. Questo è inevitabile, e dipende dalla
rappresentazione intera dei floating point. Questo vale per qualsiasi
linguaggio di programmazione.
Se non vuoi avere sorprese non usare floating point per fare confronti
di uguaglianza, e usa le apposite funzioni di approssimazione e
formattazione per fare calcoli e visualizzare i risultati.
--
news:it-alt.comp.software.openoffice : Il newsgroup dedicato a
OpenOffice.org, la suite open source di applicazioni per ufficio.

Saluti, VITRIOL
Giulio Petrucci
2007-07-26 10:50:17 UTC
Permalink
Post by Andrea
Salve a tutti,
ho notato che facedno una banalissima sottrazione tra due double il
risultato non è del tutto corretto.
Es.
double a = 2.05;
double b = 3.02;
double c = b - a;
Se si va a vedere c, viene 0.9700000000000002.
Perchè?
E' una questione relativa a come vengono rappresentati internamente i
numeri decimali. IMVHO la cosa migliore è la seguente:
- fissa la precisione di cui hai bisogno (a guardare "a" e "b" direi che
è di due cifre dopo la virgola);
- tronca il valore di "c" a quella precisione;

Ciao,
Giulio

--
VITRIOL
2007-07-26 10:55:58 UTC
Permalink
Post by Andrea
double a = 2.05;
double b = 3.02;
double c = b - a;
Se si va a vedere c, viene 0.9700000000000002.
Perchè?
Sinceramente a me, nel caso specifico, sembra che non succede:

http://img170.imageshack.us/img170/9366/calcolose3.png

Però, in linea generale, devi tenere conto che quando usi numeri in
virgola la mobile dietro l'angolo hai sempre la possibilità di un errore
di approssimazione. Questo è inevitabile, e dipende dalla
rappresentazione intera dei floating point. Questo vale per qualsiasi
linguaggio di programmazione.
Se non vuoi avere sorprese non usare floating point per fare confronti
di uguaglianza, e usa le apposite funzioni di approssimazione e
formattazione per fare calcoli e visualizzare i risultati.
--
Saluti
VITRIOL
Andrea
2007-07-26 14:49:05 UTC
Permalink
Post by VITRIOL
Post by Andrea
double a = 2.05;
double b = 3.02;
double c = b - a;
Se si va a vedere c, viene 0.9700000000000002.
Perchè?
http://img170.imageshack.us/img170/9366/calcolose3.png
Però, in linea generale, devi tenere conto che quando usi numeri in
virgola la mobile dietro l'angolo hai sempre la possibilità di un errore
di approssimazione. Questo è inevitabile, e dipende dalla
rappresentazione intera dei floating point. Questo vale per qualsiasi
linguaggio di programmazione.
Se non vuoi avere sorprese non usare floating point per fare confronti
di uguaglianza, e usa le apposite funzioni di approssimazione e
formattazione per fare calcoli e visualizzare i risultati.
--
Saluti
VITRIOL
Succede anche a te, solo che quando usi il metodo .tostring le cifre
alla fine vengono tolte.
Se provi ad utilizzare il controllo delle variabili durante il debug
te ne accorgi.
Comunque mi sembra assurda questa questione, soprattuto per numeri
razionali.
Farò delle approssimazioni, ma questa cosa continua a non piacermi!
Grazie a tutti della spiegazione
VITRIOL
2007-07-26 15:08:56 UTC
Permalink
Post by Andrea
Succede anche a te, solo che quando usi il metodo .tostring le cifre
alla fine vengono tolte.
Se provi ad utilizzare il controllo delle variabili durante il debug
te ne accorgi.
Loading Image...
Post by Andrea
Comunque mi sembra assurda questa questione, soprattuto per numeri
razionali.
Farò delle approssimazioni, ma questa cosa continua a non piacermi!
Sai quante cose non piacciono a me nella vita :-)
Non ti piacerà, ma le cose stanno così, in generale. E sono così in
tutti i linguaggi di programmazione del mondo.
Se non vuoi approssimazioni non usare tipi floating point. Usa ad
esempio Decimal.
--
Saluti
VITRIOL
Fabio
2007-07-26 16:05:45 UTC
Permalink
Post by VITRIOL
Post by Andrea
Succede anche a te, solo che quando usi il metodo .tostring le cifre
alla fine vengono tolte.
Se provi ad utilizzare il controllo delle variabili durante il debug
te ne accorgi.
http://img505.imageshack.us/img505/8008/variabilisi9.png
mmm... guarda me: Loading Image...


Ciao
VITRIOL
2007-07-26 16:19:17 UTC
Permalink
Post by Fabio
mmm... guarda me: http://img489.imageshack.us/img489/8041/variabilinw6.jpg
Sì, fa la stessa cosa anche a me su C# 2005 Express.
Prima ero su un altro PC, e avevo potuto provarlo solo su SharpDevelop,
che evidentemente si comporta in modo diverso nella visualizzazione in
debug.
Comunque sia è il comportamento normale dei floating point, da che mondo
è mondo.
--
Saluti
VITRIOL
Fabio
2007-07-26 16:38:14 UTC
Permalink
Comunque sia è il comportamento normale dei floating point, da che mondo è
mondo.
Questo è chiaro.
L'unica cosa è spiegare a Andrea che se i float e double ci sono un motivo
ci sarà.
I Decimal vanno usati se serve un'arrotondamento preciso nei calcoli ad es.
calcoli finanziari (la percentuale di un agente o le cifre in euro...), i
double in quelli scientifici (es. la distanza tra due punti, formule
matematiche...) dove l'imprecisione finale non è decisiva.
Tenendo conto che i double hanno una performance migliore.

Ciao
Fabio
2007-07-26 16:45:46 UTC
Permalink
Post by Fabio
un'arrotondamento
Aaargh!
Qui ci vuole una frustata di penitenza :)

Ciao
Mauro Servienti [MVP]
2007-07-26 15:01:13 UTC
Permalink
Ciao Andrea,
Post by Andrea
Perchè?
Usa decimal e non double che per sua natura ha questo problemi
Vedi MSDN per i dettagli

Ciao
--
Mauro Servienti
Microsoft MVP - Visual C# / MCP
http://mvp.support.microsoft.com
http://blogs.ugidotnet.org/topics
whynot [ at ] topics [ dot ] it
Raffaele Rialdi [MVP]
2007-07-26 21:49:34 UTC
Permalink
Post by Andrea
Salve a tutti,
ho notato che facedno una banalissima sottrazione tra due double il
risultato non è del tutto corretto.
Es.
double a = 2.05;
double b = 3.02;
double c = b - a;
Se si va a vedere c, viene 0.9700000000000002.
Perchè?
Perché così funziona lo standard IEEE754. Su questo e altri ng la
domanda/risposta è già stata postata più volte.
Questa è una delle tante risposte:
http://groups.google.com/group/microsoft.public.it.dotnet.asp/msg/343dff2ec6215204

Usa il decimal per numeri finanziari e per misure.
Usa il double/float per calcoli matematici.
--
Raffaele Rialdi
Microsoft .NET MVP http://mvp.support.microsoft.com -
http://italy.mvps.org UGIdotNET - User Group Italiano .NET
http://www.ugidotnet.org Weblog: http://blogs.ugidotnet.org/raffaele
Fabio
2007-07-27 07:55:32 UTC
Permalink
Post by Raffaele Rialdi [MVP]
http://groups.google.com/group/microsoft.public.it.dotnet.asp/msg/343dff2ec6215204
Usa il decimal per numeri finanziari e per misure.
Eheh, questa volta ti ho preceduto :P

Prò leggendo il tuo vecchio post mi è tornata in mente una bella domandina:
come avviene il famoso arrotondamento a 0.5 dei decimal?

In modo bancario?
Per eccesso?
Per difetto?
Posso scegliere?

(dovrei provare ma non ho voglia, magari lo sai già :P )

Ciao
Raffaele Rialdi [MVP]
2007-07-27 14:01:45 UTC
Permalink
Post by Fabio
Eheh, questa volta ti ho preceduto :P
eh si :) ma ci tenevo solo a sottolineare che è tutto corretto e secondo la
normativa IEEE
Post by Fabio
Prò leggendo il tuo vecchio post mi è tornata in mente una bella
domandina: come avviene il famoso arrotondamento a 0.5 dei decimal?
uhm, il numero viene rappresentato così com'è ... quando devi segare un
certo numero di decimali applichi una funzione ed è lei che decide.
Il metodo decimal.round fa proprio questo e qui spiega come:
http://msdn2.microsoft.com/en-us/library/system.decimal.round(VS.71).aspx
sinceramente non ricordo proprio l'algoritmo, ma il link spiega un po' di
cosette :)
--
Raffaele Rialdi
Microsoft .NET MVP http://mvp.support.microsoft.com -
http://italy.mvps.org UGIdotNET - User Group Italiano .NET
http://www.ugidotnet.org Weblog: http://blogs.ugidotnet.org/raffaele
Loading...