Newsgroup: it.comp.lang.c++
Titolo: Problema--> leggo 0.1 ed ho 0.100000001

Salve a tutti.
Il problema è il seguente .
Il mio programma legge un certo numero di valori float o double.
Utilizzo atof(..) per la conversione ma  ho provato anche strtod(..) ,il
problema resta lo stesso ,ed anche se leggo i valori direttamente float o
double in modo  cin>>d.
Il problema è che se inserisco ad esempio 0.1 ho verificato con un debbuger
che il valore realmente letto è 0.1000001 o simili , nel senso che dopo
tutti gli zeri c'e'  qualche cifra non zero .
Questo mi crea dei problemi perche' devo fare una verifica sulla somma di
tutti i valori inseriti che deve fare 1 .
Se inserisco 10 volte 0.1 ho appunto 1 ma:
if(somma !=1 )
{
   ...
   ...
}
cout<<somma;
Il codice nell'if viene eseguito come se appunto somma non è 1 ma
cout<<somma mi da 1.
Ho provato sia con bcc che con g++ è la stessa cosa.
Ciò che è anche strano è che la somma dopo 5 volte che ho inserito 0.1 si
assesta a 0.5 ma poi si ricomincia con 0.6000000023 etc...
Aiuto!

Ho provato sia con bcc che con g++ è la stessa cosa.
Il problema e' che 0.1 espresso in binario e' un
numero periodico (un po' come 1/3=0.33333... in
decimale) e quindi puo' essere rappresentato solo
in modo approssimativo dalla notazione binaria
standard dei numeri in virgola mobile.
Il fatto che stampando il valore della somma vedi
"1" significa solo che la differenza fra il valore
e 1 e' molto piccola e non merita di essere indicata
con la precisione di stampa che stai usando.
Se pensi di usare un calcolatore per fare calcoli
numerici il fatto che la rappresentazione float/double
e' approssimata e' qualcosa che devi mettere in conto
da subito.
HTH
Andrea

 con la precisione di stampa che stai usando.
Grazie della risposta .
Però mi resta il problema di come fare .
Se nel mio codice il confronto della variabile  somma con 1 fallisce quando
però in realtà è 1 come faccio ad eseguire il controllo?

 però in realtà è 1 come faccio ad eseguire il controllo?
Non hai capito; la tua somma "in realta'" *non e'* uno.  Se tu
sommassi tre volte 0.33, ti aspetteresti di ottenere uno?  Usa un tipo
numerico che sia inerentemente preciso, se vuoi dei risultati precisi.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy              ROT13: 
ybe...@cq.vasa.vg

però in realtà è 1 come faccio ad eseguire il controllo?
Normalmente quello che si fa e' aggiungere una "tolleranza",
ovvero ad esempio accetti i dati se la loro somma "s"
soddisfa la formula:
   fabs(s - 1) < epsilon
dove epsilon e' un numero piccolo che serve a tenere conto
degli errori di arrotondamento.
Per capire bene come affrontare il problema bisognerebbe
pero' sapere di piu' sul quali numeri stai sommando e perche'
la loro somma deve essere 1.
HTH
Andrea

Andrea Griffini ha scritto:


E' una distribuzione di probabilità quindi la somma fa 1.
Il programma  è implementazione dell'algoritmo di huffman. 
Il controllo è necessario perchè l'algoritmo funziona su una distribuzione
di probabilità . 
L'utente potrebbe inserire .1 .4 .25 .15 .1  che va bene , ed il controllo 
darmi che ' diverso da 1 quindi non prosegue.


Il problema non riguarda il C++, ma il calcolo numerico in genere,
qualunque linguaggio tu usi.
Prendi qualunque libro di analisi numerica e leggiti il primo capitolo;
non credo che da qualche messaggio su un newsgroup, pur con tutta la
buona volonta' che possono avere i frequentatori, tu ti possa fare piu'
di una vaga idea sul problema.
Non dovresti perderci piu' di un'oretta e fidati che ne vale la pena.
 bye
	av.

 if(somma !=1 )
*MAI* e ripeto *MAI* usare l'operatore == (e !=) con i numeri a virgola 
mobile. In qualunque linguaggio, compreso il Basic del C64... ;) 
-- 
Luc

 av.
Scusate cmq ho risolto con la soluzione di Andrea Griffini
ovvero ponendo una tolleranza.

 mobile. In qualunque linguaggio, compreso il Basic del C64... ;)
Scusa l'ignoranza, ma perchè ?


Perche' funzionera' una volta su 10000.
 bye
	av.


Ok, questo l'avevo intuito.... ma perchè non funziona?
In alternativa cosa bisogna utilizzare?
Grazie in anticipo.
Zano!

 In alternativa cosa bisogna utilizzare?
Come ti hanno gia' detto stabilisci una tolleranza
(un numero piccolo che dipende dalla precisione float/double,
ma che puo' anche dipendere da quanti errori possono essere
stati introdotti dall'aritmetica in calcoli complessi) EPS
e poi invece di controllare x==y controlli se il valore
assoluto di (x-y) e' minore di EPS.
ciao,
g.

 Perche' funzionera' una volta su 10000.
Piu' esattamente 13 volte su 10000 ;-)
Ciao,
Nicola


???
 bye
	av.

 qualunque linguaggio tu usi.
Un problema che non riguarda il c++ ha scatenato  un thread non
indifferente.
A volte non serve essere puntigliosi e stare li a fare i paladini del
newsgroup.
Se una cosa è interessante ben venga.
 I regimi dittatoriali hanno fatto tutti una brutta fine.

  I regimi dittatoriali hanno fatto tutti una brutta fine.
Non e' questione di regimi dittatoriali, quanto di pretendere dagli
altri di comportarsi in modo educato, attenendosi alle regole delle
comunita' nelle quali si inseriscono.
Devo dire che sono sbalordito da quante persone facciano fatica a
capire questi concetti.
Nicola Musatti

 luogo.
Hai ragione ma a volte la parte animalesca ha il sopravvento ... :-(
Cmq chiudiamola qui ( lo dico con il sorriso sulle labbra :-) ) con le mie 
scuse  a tutto il gruppo.     

 indifferente.
Guarda che non avevo nessun intento polemico; se cosi' sembrava me ne
scuso.
La mia era un'affermazione senza implicazioni di IT/OT; anche se forse
poteva essere utile per dove indirizzarti.
Ti ho consigliato di leggerti un capitoletto perche' credo che le
risposte (giuste) che hai avuto qui possano non bastarti; ci sono altre
cose da evitare oltre l'uso dell'operatore ==...
 bye
	av.

 > Piu' esattamente 13 volte su 10000 ;-)
Perche' tra 0 e 10000 ci stanno 13 potenze del due e siccome i soli
numeri frazionari esponibili esattamente sono le potenze negative di
due...
In realta' neanche il mio ragionamento e' esatto perche' i soli numeri
frazionari esprimibili esattamente sono le combinazioni lineari delle
potenze negative di due.
Ciao,
Nicola