C'est en effet une question intéressante, voici ce qui se passe précisément à votre matériel. Cette réponse donne les calculs exacts avec la précision de l'IEEE double
de précision flotte, c'est à dire 52 bits de mantisse plus un implicite peu. Pour plus de détails sur la représentation, voir l' article de wikipedia.
Ok, donc vous devez d'abord définir quelques variables:
double Vmax = 2.9;
double Vmin = 1.4;
double step = 0.1;
Les valeurs respectives en binaire sera
Vmax = 10.111001100110011001100110011001100110011001100110011
Vmin = 1.0110011001100110011001100110011001100110011001100110
step = .00011001100110011001100110011001100110011001100110011010
Si vous compter les bits, vous verrez que j'ai donné le premier bit est défini, plus de 52 bits vers la droite. C'est exactement la précision à laquelle votre ordinateur stocke une double
. Notez que la valeur de step
a été arrondis.
Maintenant, vous faire quelques calculs sur ces nombres. La première opération, la soustraction, les résultats dans le résultat précis:
10.111001100110011001100110011001100110011001100110011
- 1.0110011001100110011001100110011001100110011001100110
--------------------------------------------------------
1.1000000000000000000000000000000000000000000000000000
Ensuite, vous divisez par step
, qui a été arrondi par votre compilateur:
1.1000000000000000000000000000000000000000000000000000
/ .00011001100110011001100110011001100110011001100110011010
--------------------------------------------------------
1110.1111111111111111111111111111111111111111111111111100001111111111111
En raison de l'arrondissement des step
, le résultat est un peu au-dessous 15
. Contrairement à avant, j'ai pas arrondi immédiatement, parce que c'est précisément là que les choses intéressantes qui se passe: Votre CPU peut en effet stocker des nombres à virgule flottante de précision supérieure à un double
, de sorte que l'arrondissement n'a pas lieu immédiatement.
Donc, quand vous convertir le résultat de l' (Vmax-Vmin)/step
directement à un int
, votre PROCESSEUR simplement de couper les bits après la fraction de point (c'est la façon dont l'implicite double -> int
de conversion est défini par les normes linguistiques):
1110.1111111111111111111111111111111111111111111111111100001111111111111
cutoff to int: 1110
Toutefois, si vous commencez stocker le résultat dans une variable de type double, l'arrondissement a lieu:
1110.1111111111111111111111111111111111111111111111111100001111111111111
rounded: 1111.0000000000000000000000000000000000000000000000000
cutoff to int: 1111
Et c'est précisément le résultat que vous avez obtenu.