Newsgroup: it.comp.lang.c++
Titolo: Perdita di precisione?

Salve a tutti,
mi chiedevo se un costruttore di copia può far perdere la precisione con cui
si rappresenta un numero, o la rappresentazione del numero viene sempre
mantenuta, anche se il numero di decimali è veramente alto (ad es 40 o 50).
Io credo che la cosa non abbia molto senso, ma me lo chiedevo lo stesso.
Grazie per la risposta.

 mantenuta, anche se il numero di decimali è veramente alto (ad es 40 o 50).
Se effettua una copia binaria, e non un calcolo, non può perdere di precisione.
Io però sono ancora sconvolto da questo:
#include <iostream>
int main()
{
   double e = 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 - 1;
    if (e == 0)
        std::cout << "Uguale";
    return 0;
}
Fulvio.

}
Ti sconvolge anche se noti che 0.1 e' un numero periodico
quando viene espresso in binario ? E' come fare per un
calcolatore che lavorasse in decimale qualcosa come:
    0.333333333333333333333333333
   +0.333333333333333333333333333
   +0.333333333333333333333333333
   -1
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

mantenuta, anche se il numero di decimali è veramente alto (ad es 40 o 50).
Il costruttore di copia per i tipi nativi e' una copia bit-a-bit e
come tale non porta a perdite di precisione.
Nota che pero' la precisione durante i calcoli puo' superare la
precisione di memorizzazione... considera questo programma:
  #include <iostream>
  volatile double gt;
  int main()
  {
    int i;
    gt=0;
    for (i=0; i<10; i++)
      gt+=0.1;
    std::cout << gt-1 << std::endl;
    double lt=0;
    for (i=0; i<10; i++)
      lt+=0.1;
    std::cout << lt << std::endl;
    return 0;
  }
Il suo output quando viene compilato con BCC55 e'
  -1.11022e-16
  1
L'unica differenza fra i due conteggi e' che nel primo
calcolo il compilatore e' stato forzato a memorizzare
i risultati intermedi in una variabile double (la parola
"volatile" indica che potrebbe esserci qualcuno di
esterno interessato al valore di gt durante l'esecuzione
o che modifica tale variabile in maniera asincrona).
Nel secondo loop invece il compilatore ha tenuto il
risultato intermedio nei registri interni del coprocessore
che hanno una precisione superiore a quella di un double
(80 bit contro 64 per un Pentium).
Nota che comunque "40 o 50" decimali sono decisamente un
po' troppi per le rappresentazioni standard.
HTH



Ah !!!!!! no... non mi dire queste cose !!!! PANICO !!!!
No, a parte la battuta, sei riuscito a trovare qualche mezza logica che lo
spieghi?
Sebastiano

precisione di memorizzazione... considera questo programma:
...
Ci tengo a dire che ho fatto una svista nel programma mostrato
visualizzando gt-1 contrapposto ad lt. In effetti con BCC55
i risultati coincidono perche' l'ottimizzatore borland non
sfrutta la possibilita' di lasciare i risultati intermedi
sullo stack del coprocessore (basta stampare lt-1 che era
quello che volevo in realta' scrivere per vedere che il
valore visualizzato e' identico).
Il concetto di fondo e' pero' valido... durante i calcoli
intermedi e' permesso utilizzare una precisione maggiore
di quella fornita dal formato di memorizzazione e alcuni
compilatori sfruttano questa possibilita'.
Ad esempio compilando il programma corretto della svista
con gcc versione egcs-2.91.66 19990314 usando l'opzione di
ottimizzazione -O2 si ottiene:
   1.11022e-16
   5.55112e-17
Fra l'altro il compilatore gcc possiede una opzione specifica
(-ffloat-store) per disabilitare questo tipo di ottimizzazioni
nei programmi in cui la prevedibilita' e' piu' importante
della maggiore precisione e velocita'.
Mi scuso per l'errore nell'esempio mostrato precedentemente.
