这确实是一个有趣的问题,这正是在您的硬件中发生的事情。这个答案给出了 IEEE double 精度浮点数的精确计算,即 52 位尾数加一个隐式位。有关表示的详细信息,请参阅wikipedia article。
好的,所以你先定义一些变量:
double Vmax = 2.9;
double Vmin = 1.4;
double step = 0.1;
二进制中的相应值将是
Vmax = 10.111001100110011001100110011001100110011001100110011
Vmin = 1.0110011001100110011001100110011001100110011001100110
step = .00011001100110011001100110011001100110011001100110011010
如果你计算位,你会看到我给出了第一个被设置的位加上右边的 52 位。这正是您的计算机存储double 的精度。 请注意,step 的值已四舍五入。
现在您对这些数字进行一些数学运算。第一个操作,减法,得到精确的结果:
10.111001100110011001100110011001100110011001100110011
- 1.0110011001100110011001100110011001100110011001100110
--------------------------------------------------------
1.1000000000000000000000000000000000000000000000000000
然后你除以step,它已经被你的编译器四舍五入了:
1.1000000000000000000000000000000000000000000000000000
/ .00011001100110011001100110011001100110011001100110011010
--------------------------------------------------------
1110.1111111111111111111111111111111111111111111111111100001111111111111
由于step 的四舍五入,结果略低于15。与以前不同,我没有立即四舍五入,因为这正是有趣的事情发生的地方:你的 CPU 确实可以存储比 double 更精确的浮点数,所以四舍五入不会立即发生.
因此,当您将(Vmax-Vmin)/step 的结果直接转换为int 时,您的CPU 会简单地切断小数点之后的位(这就是语言标准定义的隐式double -> int 转换的方式):
1110.1111111111111111111111111111111111111111111111111100001111111111111
cutoff to int: 1110
但是,如果您首先将结果存储在 double 类型的变量中,则会进行舍入:
1110.1111111111111111111111111111111111111111111111111100001111111111111
rounded: 1111.0000000000000000000000000000000000000000000000000
cutoff to int: 1111
这正是你得到的结果。