Pourquoi cette division n'entraîne à zéro?
-
21-09-2019 - |
Question
J'écrivais ce code en C lorsque je rencontrais le problème suivant.
#include <stdio.h>
int main()
{
int i=2;
int j=3;
int k,l;
float a,b;
k=i/j*j;
l=j/i*i;
a=i/j*j;
b=j/i*i;
printf("%d %d %f %f\n",k,l,a,b);
return 0;
}
Quelqu'un peut-il me dire pourquoi le code retourne zéro pour les premier et troisième variables (k
et a
)?
La solution
Ce que je pense que vous rencontrez est arithmétique entier . Vous supposez correctement l
et b
être 2, mais supposer à tort que k
et a
sera 3 parce que c'est la même opération. Mais ce n'est pas, il est l'arithmétique des entiers (plutôt que l'arithmétique en virgule flottante). Alors, quand vous faites i / j
(s'il vous plaît envisager d'utiliser quelques espaces), 2/3 = 0,33333 ... qui est coulé à une int
et devient ainsi 0. Ensuite, on multiplie par 3 fois, et 0 * 3 = 0.
Si vous changez i
et j
être float
s (ou poivre vos calculs avec (float)
jette), cela va faire ce que vous attendez.
Autres conseils
Vous demandez pourquoi k et un spectacle comme zéro? En effet, dans la division entière 2/3 = 0 (la partie fractionnaire est tronquée).
Vous avez pas dit ce que vous obtenez ou ce que vous attendez, mais dans ce cas, il est probablement facile à deviner. Lorsque vous faites « a = i / j * j », vous attendez que le résultat soit à peu près 0,2222 (à savoir 2/9), mais vous obtenez 0.0. En effet, i et j sont les deux années int, de sorte que la multiplication et la division (cruciale) sont réalisées en mathématiques entier, ce qui donne 0. Vous attribuez le résultat à un flotteur, de sorte que 0 est ensuite converti en 0.0f.
Pour résoudre ce problème, convertir au moins un opérande à virgule flottante AVANT la division: a = (float)i/j*j);
cela est dû à la façon dont les compilateur traite c int dans les divisions:
#include <stdio.h>
int main()
{
int i=2;
int j=3;
int k,l;
float a,b;
k=i/j*j; // k = (2/3)*3=0*3=0
l=j/i*i; // l = (3/2)*2=1*2=2
a=i/j*j; // same as k
b=j/i*i; // same as b
printf("%d %d %f %f/n",k,l,a,b);
return 0;
}
Si vous vous demandez pourquoi k et sont 0: i/j*j
est le même que (i/j)*j
. Etant donné que j est supérieur à i, i/j
est 0 (division entière). 0*j
est toujours 0, alors le résultat (k) est égal à 0. De même pour la valeur de a.
il n'a pas d'importance si vous êtes variable est flottant ou non, aussi longtemps que vous utilisez
entier / entier, vous obtenez 0,
mais parce que vous utilisez une sortie flottante, vous obtenez 0.0