2014-12-07 18 views
19

Non riesco a spiegare il comportamento del seguente programma (compilato con gcc su mingw 32 bit). Sono consapevole della possibile perdita di precisione quando si converte implicitamente da double a int, ma mi aspetto che i due casi diano lo stesso output poiché sta facendo esattamente le stesse operazioni. Perché le due uscite sono diverse?Conversione da doppia a int implicita in mingw32

#include <stdio.h> 
#include <math.h> 

int main() 
{ 
    int table[3] = {2, 3, 4}; 
    int i, N; 

    N = 0; 
    N += table[0] * pow(100, 0); 
    N += table[1] * pow(100, 1); 
    N += table[2] * pow(100, 2); 
    printf("%d\n", N); 

    N = 0; 
    for(i = 0; i < 3; i++) 
     N += table[i] * pow(100, i); 
    printf("%d\n", N); 

    return 0; 
} 

//output: 
40302 
40300 

risposta

14

Con pow(100, 0)pow(100, 1) e pow(100, 2) il compilatore sostituisce la funzione chiama con costanti (1, 100, 10000), ma con pow(100, i) ha chiamare effettivamente la funzione in fase di esecuzione (a causa della variabile i essere passato come argomento), risultante con due risultati di pow nel formato 0.99999999 e 99.999999 anziché 1 e 100 (o 2 qualsiasi dei 3). Quando si tronca su int dopo il multiplo si "perdono" due unità.

Questo è un altro esempio del perché la conversione a int da double è solo male puro: molto difficile trovare bug sottili nel vostro programma (non compilatore insetti).

Btw, sono sorpreso che il compilatore con O2 non abbia srotolato il ciclo, propagando le costanti e raggiungendo la stessa ottimizzazione (sostituendo la chiamata di funzione con risultati costanti).

Btw2 Scratch che, sono sorpreso che il compilatore non ha solo sostituito tutto il codice con solo due chiamate a printf.

+0

Penso che valga la pena ricordare che lo standard C in realtà non specifica la precisione di "pow()", nemmeno che "pow()" debba dare lo stesso risultato per pow (0) e pow (i) con i = 0. Questo è stato davvero sorprendente per me, ma ha senso consentire ottimizzazioni su sistemi embedded molto piccoli. –