J’ai un petit problème de transtypage float -> int en C et je ne comprends pas trop d’où il peut venir.
Voici un programme simple illustrant mon problème:[code]#include <stdio.h>
int main()
{
int a;
float b, c, r;
a = 7;
b = 4.0 / 9.0;
c = 6.0 + 1.0 / 9.0;
r = ((a - c) / b);
printf("%f\n%d\n", r, (int)r);
return 0;
}[/code]
Et voici le retour du printf lors de l’exécution:[quote]2.000000
1[/quote]
Donc la variable r vaut 2.000000 mais sa partie entière vaut 1, et non pas 2, d’après ce programme.
Bon c’est un cas particulier, dans mon programme ce genre de cas se produisent rarement, mais ce produisent quand même, ce qui pose des problèmes. Ici je vous ai isolé un de ces cas particuliers qui me posent problème, seulement je ne comprend pas trop pourquoi.
Quelqu’un pourrait-il m’éclairer?
Comment puis-je contourner le problème simplement?
a = 7;
b = 4.0 / 9.0;
c = 6.0 + 1.0 / 9.0;
cout << " a : " << a
<< "\n b : " << b
<< "\n c : " << c;
r = ((a - c) / b);
cout << "\nR : " << r << '\n'
<< "(int)r : " << int(r)
<< hex
<< "\n0x" << *((int*)&r)
<< "\n0x" << int(r) << endl;
return 0;
}[/code]
juste rajouté des affichages (passé en C++ pour pas me prendre la tête), et le résultat est intéressant :
a : 7
b : 0.444444
c : 6.11111
R : 2
(int)r : 1
0x3fffffff
0x1
Donc à vue de pif ton flotant doit valoir 1,999999 ou un truc du genre, et il a été arrondi par la traduction en texte. Si il faisait exactement 2 y’aurait un paquet de 0 dans la mantisse normalement, hors là tous les bits sont à 1 :
[code]0011 1111 1111 1111 1111 1111 1111 1111
signe : 0 -> positif
exposant : 01111111 : 127 nickel, ça veut dire que le nombre est * 2^0
mantisse : que du 1 -> donc vu que la partie entière est implicite et est à 1
toutes les décimales sont à 1[/code]
En double la conversion en int vaut 2 dans le cas présent, oui B)
Mais j’aurais encore certainement des erreurs dans d’autres cas.
Bref, j’ai du faire une bêtise dans une fonction de calculs dans mon programme, ce qui fait qu’elle me sort quelque chose légèrement inférieur à la valeur réelle, allez savoir pourquoi. Je cherche, si je trouve pas, je posterai la fonction posant problème B)
Bah c’est un problème d’arrondis. Prends une bête calculatrice, divise 1 par 3, et tu obtiens un nombre avec un développement infini 0,333333… etc. Le problème est que l’infini en question va être tronqué en fonction des capacités de la machine, et par exemple ça va ne stocker que 8 chiffres 0,33333333. Si tu remultiplies par 3, tu obtiens 0,99999999. « (1 / 3) * 3 <> 1 » si on travaille en précision finie. Alors oui, la plupart du temps, on récupère le coup en considérant qu’un truc suffisamment proche d’une certaine valeur est la valeur en question (ce qui explique le résultat avec double). Mais ça reste incorrect.
Ce qui est important à réaliser aussi, c’est qu’un nombre qui a un développement fini en décimal n’a pas forcément un développement fini en binaire. Par exemple, on peut facilement représenter 1 / 100 en décimal (0,01) mais en binaire c’est infini. Essaie d’additionner 100 fois 0,01, et tu n’obtiendra pas 1, car la réprésentation de 0,01 en binaire est une valeur approximative.
[quote=“JDaM, post:8, topic: 32190”]Attention ça pique B) : http://docs.sun.com/source/806-3568/ncg_goldberg.html
Pour en avoir lu une bonne partie je vous assure que cette doc ouvre les yeux sur les tas de problèmes insoupsonnés (ou pas) avec les flottants.[/quote]
Il a l’air très intéressant cet article, je l’ajoute immédiatement à ma pile de “trucs à lire d’urgence”, merci JDaM !
Je viens d’essayer de trouver une illustration sur les erreurs absolues dans la représentation des entiers, j’en ai déjà vu, mais je ne retrouve plus. En fait l’idée la plus impotante à ce niveau, c’est qu’un entier perd en précision absolue au fur et à mesure qu’on s’éloigne de zéro, étant donné le principe mantisse / exposant. Ceci dit, j’ai trouvé un article et des illustrations sur les erreurs relatives, et c’est un joyeux bordel aussi : http://www.ece.uwaterloo.ca/~ece104/TheBoo…loat/error.html
Je devrais pouvoir faire un petit programme qui génère un graphe mettant en évidence les erreurs absolues. Je vais voir si j’en trouve le temps.