Newsgroup: it.comp.lang.c++
Titolo: BACO NUMERI IN VIRGOLA MOBILE!!!!

Il seguente codice C non è niente di complicato: chiede l'inserimento di un
numero e poi effettua la sottrazione tra 225 e il numero inserito. Provate a
inserire 224.7....cosa vi aspettate? 0,3 immagino. Ebbene non è così'!!!
Infatti il risultato sarà 0,300000000001   perchè mai? Se vi fermate in
debug sull'istruzione della sottrazione vedrete che i numeri 225 e 224.7
sono apparentemente corretti...invece il 224.7 è sporco (forse!!). Per
convertire la stringa 224.7 in double è stata usata la ATOF, ma usando anche
la STRTOD il risultato è lo stesso. E' forse un baco delle istruzioni
assembly? Se qualcuno sa la risposta per favore spiegatemi il problema!!!!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
void main(void);
void main(void)
{
 double x,a,b;
 a = 225.0;
 char buffer[50];
 gets(buffer);
 b = atof(buffer);
 x = a - b;
}

 inserire 224.7....cosa vi aspettate? 0,3 immagino. Ebbene non è così'!!!
Che non sia il caso di metterla nelle FAQ?
In una aritmetica in base due (o, se per questo, in qualsiasi base) ma
con un numero LIMITATO di cifre significative, non tutti i numeri
reali possono essere rappresentati in maniera esatta.  Le discrepanze
cosi' introdotte si chiamano "errori di approssimazione".
Altri errori si introducono - anche se gli operandi possono essere
rappresentati esattamente - effettuando operazioni come la
moltiplicazione, se il numero di cifre significative del risultato e'
inferiore a quello permesso dalla rappresentazione usata.
Per non parlare poi di operazioni complicate come le funzioni
trigonometriche, calcolate di prassi mediante riduzione e sviluppo in
serie...
Per questi motivi che ha qualche minimo rudimento di informatica non
si aspetta affatto che 225.0 - 224.7 faccia 0.3 .
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

Infatti il risultato sarà 0,300000000001   perchè mai? Se vi fermate in
[snip]
Con BCB4 funziona:
#pragma hdrstop
#include <condefs.h>
#include <stdlib.h>
#include <stdio.h>
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
 double x,a,b;
 a = 225.0;
 char buffer[50];
 gets(buffer);
 b = atof(buffer);
 x = a - b;
 __emit__( 0xcc );
 return 0;
}
Ciao




 piccoli e non credo che un 224,7 sia "persante" da rappresentare.
Ci sono due problemi: intanto ragioni in base dieci mentre sulla
stragrande maggioranza dei calcolatori i numeri sono rappresentati in
base binaria. Questo significa che gli unici numeri che hanno una
rappresentazione finita sono quelli nella forma 0,1 0,01 0,001 e loro
combinazioni (o meglio somme) ovvero tutti e soli i numeri che puoi
ottenere sommando 1/2 1/4 1/8 ecc.
Poiche' 0,7 non rientra in questa categoria, tale numero non ha
rappresentazione binaria finita e da qui l'errore di calcolo.
L'altro problema, piu' banale, e' che nessuno ti garantisce che il modo
di visualizzare i numeri del tuo debugger sia esatto...
Ciao,
Nicola

 molte cifre prima e dopo la virgola.
In base 10, forse.  In base 2 nemmeno 0.1 (decimale) si puo'
rappresentare con un qualunque numero finito di cifre significative.
Prova, se non ci credi: viene 0.000110011... o, espresso in ottale
per compattezza, 0.06314631463146314... --- e le ultime quattro cifre
continuano a ripetersi...


 piccoli e non credo che un 224,7 sia "persante" da rappresentare.
Non e` questione di "peso", ma di IMPOSSIBILITA` di rappresentare
esattamente (in binario) un numero razionale il cui denominatore (una
volta ridotto ai minimi termini) non e` una potenza di 2.
La rappresentazione decimale ha esattamente lo stesso problema nel
rappresentare esattamente i razionali il cui denominatore (ai m.t.)
contenga fattori primi diversi da 2 e 5 (i fattori primi della base, 10).
Si tratta di considerazioni assolutamente elementari, eppure queste
problematiche vengono sollevate su questo gruppo con una frequenza
scoraggiante.  Paolo, dovremmo sicuramente mettere qualcosa in
merito nelle FAQ... continuo a consigliare il tutorial di calcolo numerico
che si trova alla URL 
http://info.rutgers.edu/Techdir/lang-5.0/DOC5.0/
lib/locale/C/html/common/ug/index.html (una sola riga, divisa qui per
pura comodita`).
Alex

 > Questa č la mia domanda. Se riesce a farlo a sottrazione avvenuta puň


 gesitre la cosa con ulteriori codice.
Come da mio messaggio precedente, se c'e` un mucchio di
aritmetica FP e una totale mancanza di comprensione dei
principi piu` elementari del calcolo numerico non credo
proprio che sia il controllo sull'arrotondamento del bit meno
significativo (che alcuni compilatori offrono, supportando lo
standard IEEE del floating-point a preferenza dello standard
C++ che invece in merito non ha nulla da offrire) possa
essere di nessun ausilio.
Alex

 scoraggiante.
Devi però considerare che chi le solleva potrebbe essere un
programmatore alle prime armi. A me capitò di scontrarmi con questo
problema nel 1982, quando presi in mano il mio primo computer (un
Sinclair ZX81), e all'epoca non riuscivo a capacitarmi. Pensavo fosse
rotto. Poi capii e da quel momento non me ne sorprendo più.
EMG

Che non sia il caso di metterla nelle FAQ?
Un intero corso di calcolo numerico?
Comunque mettero` qualcosa... fatevi sotto con domande e risposte...
Non garantisco sui tempi!
Paolo
--------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
--------------------------------------------------

pura comodita`).
Mi sa che sarebbe meglio istituire il primo corso di calcolo numerico
su NG!!!!!!!!!
Cerchero` di fare qualcosa per quanto riguarda la faq... ma datemi tempo
perche` sono oppresso da scadenze decisamente piu` importanti.
