2010-09-05 4 views
2

J'ai récemment rencontré un problème où je n'obtenais pas le résultat numérique que je m'attendais. Je dépisté vers le bas au problème qui est illustré par l'exemple suivant:Pourquoi deux multiplicateurs à virgule flottante donnent-ils une réponse différente d'un?

#include <stdio.h> 

int main() 
{ 
    double sample = .5; 
    int a = (int)(sample * (1 << 31)); 
    int b = (int)(sample * (1 << 23) * (1 << 8)); 
    printf("a = %#08x, b = %#08x\n", a, b); 
} 
// Output is: a = 0xc0000000, b = 0x40000000 

Pourquoi est le résultat de la multiplication par (1 < < 31) différent du résultat de la multiplication par (1 < < 23) * (1 < < 8)? Je m'attendais à ce que les deux donnent la même réponse mais ils ne le font pas.

Je dois noter que toutes mes valeurs à virgule flottante sont dans la plage [-1, 1).

+0

Votre code et votre question sont différents. – leppie

+1

Merci, j'ai modifié la question pour correspondre au code. – sbooth

Répondre

14

Vous attendez apparemment des résultats identiques puisque vous supposez que multiplier par (1 << 31) est identique à multiplier par (1 << 23) puis par (1 << 8). En général, ils ne sont pas identiques. Vous effectuez le calcul (1 << 31) dans un domaine signed int. Si votre plate-forme utilise des bits 32 bits, l'expression (1 << 31)déborde de, tandis que (1 << 23) et (1 << 8) ne débordent pas. Cela signifie immédiatement que le résultat de la première multiplication est imprévisible. En d'autres termes, cela n'a aucun sens de faire (1 << 31) sur une plate-forme qui n'a que 31 bits dans la représentation de valeur de type int. Vous avez besoin d'au moins 32 bits de formation de valeur pour calculer de manière significative (1 << 31).

Si vous voulez que votre (1 << 31) donner un sens, dans ce Calculons le domaine non signé : (1u << 31), (1u << 23) et (1u << 8). Cela devrait vous donner des résultats cohérents. Vous pouvez également utiliser un type entier signé plus grand.

+0

Explication très claire, merci. – sbooth

Questions connexes