Problemi con la precisione

di il
2 risposte

Problemi con la precisione

Saluti a tutti,

usando g++ su Ubuntu, processore Intel Core 2 Duo, ho trovato questo comportamento apparentemente anomalo.
Eseguendo:

double x, y, a;
x = pow(10.0,20.0);
y = -x;
a = 1000.0;
x += a;
printf(" x + y = %f \n", x + y);
Ottengo correttamente come risultato: x + y = 0.000000, in quanto 10^20 sommato a 1000 dà ancora 10^20 in formato ieee 754 double precision a 64 bit (ho controllato bit a bit).

Se però al posto delle ultime due righe metto:
printf(" x + y = %f \n", (a + x) + y);
Allora ottengo correttamente: x + y = 1000.000000
Non riesco a capire il motivo di tale apparente anomalia. Forse i registri per il calcolo delle espressioni hanno più di 64 bit?
Ponendo a = 1 ottengo x+y = 0, a = 10 ottengo x+y = 8, a = 100 ottengo x+y = 96.

Qualcuno sa spiegarmi perché?

Grazie

Michele

2 Risposte

  • Re: Problemi con la precisione

    Ciao michelem,

    io non ho il problema che riscontri x86_64 Gnu/Linux. In entrambi i casi ottengo zero.
    
    max@studio:~> g++ -v
    Using built-in specs.
    COLLECT_GCC=g++
    COLLECT_LTO_WRAPPER=/usr/lib64/gcc/x86_64-suse-linux/4.5/lto-wrapper
    Target: x86_64-suse-linux
    Configured with: Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.5 --enable-ssp --disable-libssp --disable-plugin --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --disable-libmudflap --with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --program-suffix=-4.5 --enable-linux-futex --without-system-libunwind --enable-gold --with-plugin-ld=/usr/bin/gold --with-arch-32=i586 --with-tune=generic --build=x86_64-suse-linux
    Thread model: posix
    gcc version 4.5.1 20101208 [gcc-4_5-branch revision 167585]
    
    Prova a dare un occhiata al manuale probabilmente è semplicemente un parametro tipo -fexcess-precision o roba simile altrimenti apri un report in gcc@bugzilla

    ~Max

    EDIT:
    ATTENZIONE! Ho verificato la condizione compilando a 32bit.
    -ffloat-store
    Might help a Fortran program that depends on exact IEEE conformance on some machines, but might slow down a program that doesn't.

    This option is effective when the floating-point unit is set to work in IEEE 854 `extended precision'---as it typically is on x86 and m68k GNU systems--rather than IEEE 754 double precision. `-ffloat-store' tries to remove the extra precision by spilling data from floating-point registers into memory and this typically involves a big performance hit. However, it doesn't affect intermediate results, so that it is only partially effective. `Excess precision' is avoided in code like:


    a = b + c
    d = a * e

    but not in code like:


    d = (b + c) * e

    For another, potentially better, way of controlling the precision, see @xref{Floating-point precision}.
    
    max@studio:~> gcc prova.c -m32
    max@studio:~> ./a.out 
    sizeof (double)=8
     x + y = 0.000000 
     x + y = 1000.000000
    max@studio:~> gcc prova.c -m32 -ffloat-store
    max@studio:~> ./a.out 
    sizeof (double)=8
     x + y = 0.000000 
     x + y = 0.000000 
    max@studio:~>
    
  • Re: Problemi con la precisione

    Il mio manuale riporta meglio il quote precedente preso dal web:
    -ffloat-store
    Do not store floating point variables in registers, and inhibit other options that might change whether a floating point value is taken from a register or memory.

    This option prevents undesirable excess precision on machines such as the 68000 where the floating registers (of the 68881) keep more precision than a "double" is supposed to have. Similarly for the x86 architecture. For most programs, the excess precision does only good, but a few programs rely on the precise definition of IEEE floating point. Use -ffloat-store for such programs, after modifying them to store all pertinent intermediate computations into variables.
    Questo è chiaro e limpido. stai compilando a 32bit!

    edit: ho detto una ca...ata, se segui col debug capisci il motivo...
    il registro ST0 e' di 80 bit sugli x86 (non e' l'unico, ma quello usato nelle operazioni). se non poppi/pushi (salvi e ricarichi) nei calcoli ottieni questo inconveniente.
    ti allego link wiki http://en.wikibooks.org/wiki/X86_Assembly/Floating_Point con esempio asm chiarificatore.

    Max
Devi accedere o registrarti per scrivere nel forum
2 risposte