Les formats de nombres flottants courants, en particulier IEEE 754, ne stockent pas l'exposant en tant qu'entier simple, et le traiter comme un entier ne produira pas de résultats corrects.
En flottant 32 bits ou double 64 bits, le champ de l'exposant est de 8 ou 11 bits, respectivement. Les exposants codés de 1 à 254 (en flottant) ou de 1 à 2046 (en double) agissent comme des entiers : si vous ajoutez un à l'une de ces valeurs et que le résultat est l'une de ces valeurs, alors la valeur représentée double. Cependant, ajouter un échoue dans ces situations :
- La valeur initiale est 0 ou subnormale. Dans ce cas, le champ de l'exposant commence à zéro, et en ajoutant un, on ajoute 2-126 (en flottant) ou 2-1022 (en double) au nombre ; cela ne double pas le nombre.
- La valeur initiale dépasse 2127 (en flottant) ou 21023 (en double). Dans ce cas, le champ de l'exposant commence à 254 ou 2046, et en ajoutant un, on change le nombre en un NaN ; cela ne double pas le nombre.
- La valeur initiale est l'infini ou un NaN. Dans ce cas, le champ de l'exposant commence à 255 ou 2047, et en ajoutant un, on le change en zéro (et il est susceptible de déborder dans le bit de signe). Le résultat est zéro ou subnormal mais devrait être l'infini ou un NaN, respectivement.
(Ce qui précède est pour les signes positifs. La situation est symétrique avec les signes négatifs.)
Comme d'autres l'ont noté, certains processeurs n'ont pas de moyens pour manipuler rapidement les bits de valeurs à virgule flottante. Même sur ceux qui le font, le champ de l'exposant n'est pas isolé des autres bits, donc en général, vous ne pouvez pas ajouter un sans déborder dans le bit de signe dans le dernier cas mentionné ci-dessus.
Bien que certaines applications puissent tolérer des raccourcis tels que négliger les subnormales ou les NaN ou même les infinis, il est rare que les applications puissent ignorer zéro. Étant donné que l'ajout d'un à l'exposant échoue à manipuler correctement zéro, il n'est pas utilisable.
10 votes
Quelle est votre question ?
3 votes
La question est pourquoi le compilateur ne convertit-il pas les multiplications par 2 à virgule flottante en incréments d'exposant comme il le peut pour les entiers et les décalages.
1 votes
Je sais que cela peut se faire, mais est-ce que les compilateurs en général le font ? Sont-ils déjà assez intelligents ? Ou dois-je le faire moi-même ?
0 votes
Je suppose que je dois faire un benchmark
int * float
vsldexp()/frexp()
vsscalbnf()
. Ce serait mieux si quelqu'un l'avait déjà fait.0 votes
Je pense que la conclusion à laquelle nous pouvons arriver est que c'est trop marginal pour que les rédacteurs de compilateurs s'en préoccupent - surtout que ce type de matériel est presque inexistant de nos jours. Donc si vous pensez pouvoir faire mieux que le compilateur, allez-y. Battre le compilateur n'est pas impossible. Étant moi-même programmeur HPC de bas niveau, je bats le compilateur tout le temps.
1 votes
Peut-être que cette exigence relève de cette catégorie où les personnes assez intelligentes pour le vouloir sont mieux placées pour le mettre en œuvre par elles-mêmes que de répondre aux âmes inférieures de stackoverflow ce qui se passe...
4 votes
@user1095108: J'ai fait un benchmark de ldexp/increment/frexp. Au moins dans mes tests (VC++ et gcc, sur x86), une multiplication était beaucoup plus rapide.
3 votes
mon test montre également que la multiplication est environ 134 fois plus rapide que
scalbln
.