Newsgroup: it.comp.lang.c++
Titolo: URGENTE!!!Gestione numeri in virgola mobile

Ho un programma gigantesco che fa molte operazioni con numeri in virgola
mobile che sappiamo essere "pericolosi" in quanto a approssimazioni e
rappresentazioni numeriche. Ebben vorrei sapere se c'č un modo per evitare
di ricercare in tutto il programma i punti in cui fa queste operazioni
aritmetiche e far sě che a ogni operazione il risultato sia automaticamente
arrotondato. Non c'č una qualche direttiva o qualsivoglia cosa che mi
permetta di fare ciň?
Ringrazio in anticipo

Claudio Marinozzi <marin...@beta80.it_NOSPAM> wrote in message
news:95140382...@eva.enter.it...

Non in C++ Standard, ma applicando lo standard IEEE puoi controllare
il "rounding mode" fra le varie altre cose (_controlfp in VC++6, ad es).
Tuttavia, dubito che il controllo del "rounding mode" ti sia particolarmente
utile -- esso determina solo la direzione di arrotondamento del bit meno
significativo del significante, e non ha nulla a che vedere con una
ipotetica
rappresentazione _decimale_ del numero, che, mi pare di capire dai
recenti messaggi, e` per una qualche ragione il tuo focus di interesse.
Alcuni compilatori permettono (a prezzo di ENORMI rallentamenti
nell'esecuzione) di applicare una libreria di run-time che funziona in
modalita` decimale invece che binaria relativamente al floating-point;
non ne conosco pero` nessuno di recente (era ad esempio una delle
feature del "Lightworks C" una dozzina d'anni fa circa).
Mediamente, chi si preoccupa tanto della rappresentazione decimale
dei numeri ha probabilmente una comprensione insufficiente della
natura dell'aritmetica floating point, per cui e` molto probabile che
nel suo codice vi siano ben altri problemi, che nessuna libreria di
runtime puo` far nulla per risolvere.
Ad esempio, l'utente "ingenuo medio" pensa, poveretto, che
    a + b + c
sia eguale a
    a + c + b
e quindi non si preoccupera` mai, quando scrive un programma
che deve sommare dei numeri floating-point, di farlo nell'ordine
GIUSTO, quello che non rischia di bruciare numeri arbitrari di
cifre di precisione.  Non ci sono librerie che tengano.
D'altra parte, il programma di controllo dei sia pur ottimi
antimissili "Patriot" soffriva esattamente di questo errore
concettuale (e fu per quello che un missile iraqeno riusci`
a passare la barriera e distruggere una caserma di marines);
ai tempi della guerra del Golfo insegnavo calcolo numerico
all'universita`, quindi quando questa informazione fu resa
pubblica ne approfittai al fine di fissare bene in testa ad
almeno una generazione di studenti questo principio del
tutto elementare ma altrettanto fondamentale.  (L'analisi
di quell'errore e` d'altronde illuminante da vari punti di
vista di ingegneria del software e calcolo numerico).
Alex

 wrote in message
news:893o1r$saf$1...@serv1.iunet.it...


 cifra decimale.
Non e` questione di troncamenti piuttosto che di arrotondamenti, ma di
aritmetica decimale (come tu continui a richiedere) piuttosto che binaria
(come i computer moderni implementano, in modo pressoche` esclusivo,
e come il C++ ti pone a disposizione).  _controlfp ti permette di accedere
alle funzionalita` della floating-point unit e quindi di controllare vari
modi
di arrotondamento (e anche troncamento) ma ***IN BINARIO***.
***NON*** in decimale.
Quindi NON "all'ottava cifra decimale", e neppure alla settima, o alla
sesta, alla quinta, e via contando.
UNICO modo di ottenere il funzionamento di cui tu continui ad
esprimere il desiderio, cioe` in aritmetica decimale, e` di agganciare
in qualche modo un pacchetto di aritmetica decimale.  Non ne
conosco, immagino che ne esistano parecchi.  Presumibilmente
definiranno un tipo-numerico base simile a
class number {
    // ... tutti i vari operatori ecc ecc
    // per simulare strettamente double,
    // ma in decimale
};
e potrai usare "automagicamente" questo, invece di double,
con un
#define double number
da qualche parte nei tuoi header precompilati.
Una rapida ricerca su Google suggerisce di esaminare a questi
scopi i pacchetti che trovi su 
oonumerics.org/oon/
 -- qualcuno
del tipo apfloat, hfloat, CLN, fPoint; oppure Piologie, che trovi a
ftp://ftp.informatik.uni-tuebingen.de/pub/CA/software/Piologie/piologie.html
o simili.  Queste librerie tendono ad essere orientate a mettere
a disposizione "precisione illimitata", dovrai studiare un minimo
le loro doc per vedere quali di esse ti permettono invece di dare
tu delle specifiche di precisione *in termini di aritmetica decimale
e non binaria* (il che e` sicuramente POSSIBILE, come lo sarebbe
usare una qualsiasi altra base prefissata, visto che qui tutto e`
simulato in software invece di usare la Floating-Point Unit che
l'hardware mette a disposizione... visto che la FPU e` binaria!).
Alex

In realta' il problema puo' essere visto anche da un'altro punto di
vista, ovvero di garantire che i numeri "escano" dal programma nel
formato decimale desiderato: ovvero come problema di formato di output
(verso file, a video, su database). Puntando cioe' ad un opportuno uso
di strumenti come i manipolatori degli streams o la buona vecchia
printf. E' chiaro che questo approccio prescinde completamente dalla
correttezza dei calcoli, ma se e' piu' importante avere esattamente n
cifre decimali che avere i risultati migliori che si possono ottenere...
Ciao,
Nicola


Non so se č quello che cerchi ma il compilatore della Borland fornisce il
tipo
bcd :   binary-coded decimals (BCD).
L'header č bcd.h ed č una classe C++
Manlio Perillo

virgola posso anche troncare il numero.
Il problema non e` tanto troncare o arrotondare... Niente ti garantisce
che le 7-8 cifre che ti interessano siano esatte...
Ad esempio potresti ottenere una rappresentazione che pur avendo
un errore relativo dell'ordine della precisione di macchina, non ha
in effetti alcuna cifra esatta...
Ovvero un numero come 4.999999999999999998 potrebbe (non ho verificato)
essere approssimato con 5.0 con nessuna cifra significativa esatta!
Quando si opera con l'aritmetica floating point non si pretende
di lavorare con numeri precisi, ma con valori che approssimano
quello esatto con uno scarto percentuale legato alla precisione
di macchina ed al condizionamento del problema.
Potresti pensare di lavorare con numeri in virgola fissa, pero`
il C++ non mi pare fornisca tale aritmetica (ta le devi implementare
oppure trovare una implementazione gia` pronta).
Paolo
P.s.
  A chi interessa l'argomento posso consigliare un testo introduttivo...
  "Introduzione alla matematica computazionale" di
  Bevilacqua, Bini, Capovani e Menchi
  edito da Zanichelli.
  Non e` un libro esaustivo, ma tratta il problema quanto basta per
  dare una idea sufficiente del problema.
--------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
--------------------------------------------------

 che questo non deve essere scritto come 0,3000...01, ma come semplice 0,3.
Se non vuoi fare i salti mortali, perche' non usi un aritmetica intera?
Ad esempio, se il tuo numero deve esprimere una cifra in euro e devi
troncare a livello dei centesimi in maniera esatta, perche' non salvi
nel tuo database un valore intero in centesimi?
Purtroppo non c'e' un modo semplice di far diventare esatti i numeri
in virgola mobile.
OT: qual'e' il plurale di "euro"?  Alla televisione sembra invariante
(un euro, due euro) - nonostante le attuali valute abbiano singolare
e plurale (una lira, due lire; un franco, due franchi).  Devo riconoscere
che "due euri" suona male...
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

Ho provato a fare la seguente cosa in VC++ 5.0:
void main(void)
{
     double a,b,c;
    a = 225.0;
    b = 224.7;
    c = a - b;    //qui c vale 0.30000000000001
    Converti(&c);
    double d = c; //qui c vale 0.30000000000000  !!!!!! e lo stesso d
}
void Converti(double* x)
{
char buffer[20];
_gcvt(*x,10,buffer); //Converte da double a stringa
*x = atof(buffer); //Converte da stringa a double
}
Funzione per quello che voglio fare io...avere un 0.3 pulito, un 0.3 da
informatica gestionale diciamo. Avrò forse dei problemi (non ho ancora
provato) con numeri la cui rappresentazione è 0.2999999999998 ad esempio.
Però è già qualcosa.
Mi chiedo come mai all'uscita della Converti il 0.3, che è sempre non
rappresentabile in modalità binaria, viene visto pulito.
Voglio comunque ringraziare tutte le persone che mi hanno dedicato del tempo
per questo mio problema della virgola mobile :o))