Newsgroup: it.comp.java
Titolo: Java non sa fare le addizioni ???

Forse la questione era già stata proposta, boh!
ad ogni modo la situazione è questa: una JSP legge
una tabella da MySQL e totalizza per cliente, in
alcuni casi da risultati con 00000000002 nei
decimali. Ho provato a uscire dall'ambiente
Tomcat+MySQL e ho creato questa classe:
class  prova
{
 public static void main(String[] args)
 {
   double mc1, mc2, mc3, mc4, mc5, mc6, mc7, mc8, mc9, mc10, mc11, totc;
   mc1  = 00000046.48;
   mc2  = 00000030.37;
   mc3  = 00000017.51;
   mc4  = 00000008.75;
   mc5  = 00000066.52;
   mc6  = 00000222.90;
   mc7  = 00000153.68;
   mc8  = 00000008.33;
   mc9  = 00000005.21;
   mc10 = 00000047.51;
   mc11 = 00000424.73;
   totc = mc1 + mc2 + mc3 + mc4 + mc5 + mc6 + mc7 + mc8 + mc9 + mc10 + mc11;
   System.out.println(mc1);
   System.out.println(mc2);
   System.out.println(mc3);
   System.out.println(mc4);
   System.out.println(mc5);
   System.out.println(mc6);
   System.out.println(mc7);
   System.out.println(mc8);
   System.out.println(mc9);
   System.out.println(mc10);
   System.out.println(mc11);
   System.out.println("Totale: " + totc);
 }
}
ebbene questo è il risultato:
C:\JavaLab>java prova
46.48
30.37
17.51
8.75
66.52
222.9
153.68
8.33
5.21
47.51
424.73
Totale: 1031.9900000000002
mentre il totale corretto
è 1031.99
sbaglio qualcosa io ?
cosa si può usare invece di double
per gestire gli importi in euro ??
Grazie,
Saluti.

 decimali.
Normale problema di gestione dei numeri in virgola mobile.
Arrotonda al 2o decimale.
Davide
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Non toccare questo tasto altrimenti ti uccidono..............
Soprattutto non usare toni polemici sulle capacità di calcolo sui numeri in
virgola di Java.
Senti io tempo fa lanciai la stessa critica.
Dopo qualche giorno ho preferito interrompere una discussione che tanto non
avrebbe portato da nessuna parte e che non avrebbe di certo giovato a
nessuno.
Allora, la soluzione è questa.
Usa la classe BigDecimal.
ATTENZIONE !!!!!!!!
Passagli i numeri come stringhe, perchè se glie li passi come double, fa
delle cose abbastanza bizzarre.
Ricordati che il risultato di una operazione con BigDecimal, viene passato
in output, quindi se vuoi sommare il numero X1+X2 memorizzandolo dentro X1,
devi fare X1 = X1.add(X2);
con il metodo  setScale puoi definire il numero di cifre decimali, e anche
il tipo di arrotondamento.
Bye.

 sbaglio qualcosa io ?
No, è il modo in cui i numeri in virgola mobile vengono gestiti. Sul DB puoi
usare il tipo corrispondente al java.sql.Type.NUMERIC o DECIMAL, BigInteger.
(IIRC)
Ciao,
 Stefano
----------
"X WindowSSS, teSSSoro mio... lo odieremo per SSSempre"
Bill Gollum
----------

(IIRC)
fate attenzione al metodo get/setBigDecimal se usate i driver JDBC di
Oracle (non ricordo quale versione...).
Un programmino di esempio che non faceva altro che scrivere e
rileggere BigDecimal ha rilevato che ogni tanto venivano scritti
numeri completamente sbagliati...
--
Kali
"Therefore... There are patterns everywhere in nature"

nessuno.
hahahaha dai accidenti non te la sarai mica presa? ;))
peace,


> hahahaha dai accidenti non te la sarai mica presa? ;))
No, non ti preoccupare.
Però sono rimasto della mia idea.
La cosa brutta è che quella CARATTERISTICA di Java è venuta fuori dopo che
avevo scritto già alcune cose.
Diciamo che ho dovuto rimettere mano a non poco codice per riscriverlo con
il BigDecimal

 La cosa brutta è che quella CARATTERISTICA di Java è venuta fuori dopo che
Avevo seguito la discussione che avevi lanciato qualche tempo fa e una cosa
mi sembra che non fosse stata chiaramente ribadita: questi "problemi" di
calcolo NON sono una caratteristica di Java. Sono problemi attinenti alla
natura stessa, in un computer come in una calcolatrice da tasca, della
rappresentazione di numeri reali con un sistema in base 2. Semplicemente non
si puo' rappresentare tutti i numeri reali, cioé un'infinità, con un numero
finito di bit. Capita che per esempio il numero 1031.99 non sia
rappresentabile esattamente come double a 64 bit, ma solo con
un'approssimazione come 1031.9900000000002.
Ribadisco che questo non ha niente a che vedere con il linguaggio
utilizzato. Perché allora regolarmente ritorna questa diatriba con Java?
Perché Java, contrariamente a quasi tutti i linguaggi, non arrotonda
automaticamente **l'output**. In C come in Java internamente il valore sarà
sempre 1031.9900000000002 ma le funzioni di output in C, come printf() e
affini, arrotondano a 1031.99 e nessuno manda messaggi increduli sui
newsgroup...
bye
Carlo Jelmini

 wrote in message
news:fG5c8.15407$8F6.6...@twister2.libero.it...

Riposto un articolo di qualche tempo fa:
...il problema sta nella distinzione tra numeri razionali (Q) e numeri reali
(R). Mentre i numeri razionali sono rappresentabili un con numero finito di
cifre, l'insieme dei numeri reali (contenente il sottoinsieme Q) ha in più
numeri *non* rappresentabili con un numero finito di cifre; ad esempio:
Numero razionale (e quindi anche reale): q = 10/4 = 2.5
Numero reale: r = 10/3
Se volessi scrivere r per esteso non finirei mai di digitare 3, a meno di
fermarmi ad una certa posizione decimale (approssimazione). Se quindi
rimoltiplicassi tale valore per 3, non otterrei 10...
Quanto detto è:
- indipendente dalla rappresentazione dei numeri sul calcolatore, e quindi
- indipendente dal linguaggio di programmazione
- una delle basi dell'analisi matematica
- un problema che nessun calcolatore, essendo finito per definizione, potrà
mai risolvere
HTH,
Fausto.

 Per• sono rimasto della mia idea.
Errare e' umano, perseverare.. :-)
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

 avevo scritto già alcune cose.
Sembra che il thread non ti sia servito a molto... peccato!
P.S. non tutto e' opinabile
uL

rappresentazione di numeri reali con un sistema in base 2. 
Appunto. Qualche giorno fa qlc si lamentava della stessa
cosa in Perl (su it.comp.perl ).
Ci saranno centinaia di libri (di centinaia di pagine) che
trattano di epsilon macchina, propagazione dell'errore,
arrotondamenti, tolleranza etc.
Saluti!
-- 
WEbdOM webmaster di
Metronic.It mobile phone philosophy
www.gadgetpoint.it
 serigrafia on line

newsgroup...
prego tutti i santi del paradiso che quello che scrivi sia recepito :)
ciao_O
_______________________________________
http://jame.sourceforge.net
 

- indipendente dalla rappresentazione dei numeri sul calcolatore,
Sbagliato. Se il programma precedente viene scritto
con un linguaggio con rappresentazione dei numeri BCD
(ce ne sono alcuni) il risultato sara' corretto, cioe' zero.
Questi errori dipendono proprio dalla rappresentazione!
Ciao
Luigi


Hai ragione e mi scuso col NG per la boiata sentenziata! Ad ogni modo rimane
vera l'affermazione che gli "errori" di calcolo fatto notare sono dovuti
alla rappresentazione dei numeri utilizzata dal calcolatore...
Fausto.

 >newsgroup...
 Ok e fin qui sono daccordo con te.
N.B. non è un'altra discussione ma solo un tema di
approfondimento....................... Non è una critica !!!!!!!
Faccio un rapido passo in dietro per farvi capire da dove nascono le mie
perplessità :
Io a scuola ho sempre usato il bellissimo Turbo C e per i primi anni il
mitico Pascal.
I PC erano 286 quindi niente coprocessori matematici etc.
Saprete sicuramente che sia il Turbo C che il Turbo Pascal hanno lo stesso
identico ambiente di sviluppo, dotato di debugger.
Quando facevo le mie piccole applicazioncine (soprattutto in C) e usavo
variabili a virgola mobile, durante il debugging (quindi niente funzioni
printf etc.) i valori risultavano sempe corretti e privi di questi errori
dovuti alle caratteristiche che voi mi avete spiegato.
Scusate li chiamo errori secondo la matematica tradizionale, l'algebra pura
e semplice.
Forse è meglio chiamarli approssimazioni?
Probabilmente il C fa già un arrotondamento in automatico?
Mi viene in mente solo questa di soluzione.
Capirete che mi è rimasto molto difficile accettare che linguaggi molto più
evoluti e che oltretutto discendono dal C, possano invece mostrare queste
approssimazioni imposte dalle strutturre dei calcolatori.
A questo punto mi chiedo a che serve la variabile double, vista
l'impossibilità ad utilizzarla.
Non era meglio mascherare la classe BigDecimal con un double? Gli utenti
avrebbero pensato di utilizzare un tipo dato elementare e non avrebbero mai
detto nulla.
Ciao a tutti e bun lavoro.


Esatto!!
e chi come me proviene da ambienti mainframe
o midrange e ha utilizzato altri linguaggi nei quali, se
definisci una variabile di 9 cifre di cui 2 decimali,
quella così è e così rimane tende a dare per scontate
diverse cose.

 increduli sui newsgroup...
In ogni caso è sempre meglio che sia tu a decidere...
-- 
Antonello Pasella

 sbaglio qualcosa io ?
Si, a prendere un risultato con piu cifre di quelle che sono 
significative...
Hai messo numeri a DUE cifre decimali?
E allora leggine due!!
Esempio:
Se un tester ha tre cifre decimali (significative) vuol dire che il 
produttore ti da la garanzia che quelle tre cifre sono esatte. L'attrezzo 
internamente ne usa di piu, e se tu le vai a leggere non ti puoi lamentare 
con il produttore ;-P
spero di essermi spiegato
ciao :)
-- 
Antonello Pasella

Lo ammetto, ho detto una bufala enorme...
In un mondo di fanfaroni, arrampicatori sugli specchi e
scaricatori di barili, mi da' ottimismo trovare una
persona che ammette onestamente un proprio errore.
Grazie e complimenti sinceri!
Luigi

 Hai ragione e mi scuso col NG per la boiata sentenziata! Ad ogni modo rimane
...la modestia...
...e mi scuso a mia volta per l'OT :)
tityrus
PS il tuo messaggio è di una specie talmente rara che andrebbe messo nella faq :)

 dovuti alle caratteristiche che voi mi avete spiegato.
Dubito che tu andassi a leggerti i valori in virgola mobile direttamente
nella loro rappresentazione binaria, dunque deduco che tu voglia dire che il
debugger ti **presentasse** i dati come corretti. Indovina cosa usa un
debugger per presentarti questi dati? Le solite funzioni di output che
arrotondano alle sole cifre significative...
A Java si puo' rimproverare solo il fatto che l'output per default di un
double o di un float non sia abbastanza "intelligente" da evitare di
mostrare queste approssimazioni. Ma non accusiamolo di non saper contare.
Esiste tutta una disciplina, l'analisi numerica, che si occupa di questo
genere di problemi legati alla matematica discreta.
Consiglio una visita al Java Glossary alla voce Floating Point:
http://mindprod.com/gloss.html
 (mi dispiace non ho trovato niente in
italiano). Spiega bene tutti i problemi.
bye
Carlo Jelmini
PS:
<Affermazione basataSu="vago ricordo" daVerificare="Yes">
in realtà, nel design di Java i double e i float non erano previsti per
essere visualizzati direttamente (salvo che per debug), ma sempre passando
da classi come DecimalFormat per controllarne finemente il formattaggio.
</Affermazione>

 il formattaggio.
Votate *jelmo* come nostro candidato al concorso *il neologismo
dell'anno* :-}
Ciao,
Mauri.
-- 
La forza di gravitą č un falso mito,
č la Terra che succhia!

 arrotondano alle sole cifre significative...
Grazie per la chiarificazione.
Da oggi giuro che non romperò più le scatole su questo tema.
Promesso.

 dell'anno* :-}
Faccio ammenda. Mi é scappato un francesismo. Purtroppo dopo 13 anni passati
a Ginevra il mio italiano non é più quello di prima...
Come si dice in vero italiano?
bye
Carlo

Come si dice in vero italiano?
la formattazione? :)



<pignolo>Temo non esista un termine in *vero italiano*, formattazione
è il termine tecnico comunemente usato ed è esso stesso, ritengo, un
neologismo anglofono.</pignolo>
Avete idea del casino che sarebbe se i linguaggi di programmazione
subissero la stessa tipologia di *automutazioni* dei linguaggi
*naturali*?
Ciao,
Mauri.
-- 
La forza di gravità è un falso mito,
è la Terra che succhia!