以下示例来自于《发现现代 C++》一书的第 14 页,Peter Gottschling。作者指出:
为了说明这种转换行为,让我们看下面的例子:
long l = 1234567890123;
long l2 = l + 1.0f - 1.0; // imprecise
long l3 = l + (1.0f - 1.0); // precise
Run Code Online (Sandbox Code Playgroud)
这导致作者的平台:
l2 = 1234567954431;
l3 = 1234567890123;
Run Code Online (Sandbox Code Playgroud)
我的问题是究竟是什么导致了这种不精确?是不是由于加法和减法的左结合性,所以l2计算为(l + 1.0f) - 1.0?如果是的话,肯定是值范围3.4E +/- 38 (7 digits)的float(见)覆盖的价值1234567890123,使我的知识狭窄不应该是一个问题。
Afloat通常是 32 位。你如何看待它实现更大的范围(最大值~3.4e38相比同尺寸的)int,为此,最大值为~2.1e9?
唯一可能的答案是它无法在达到最大值的过程中存储一些整数。并且可表示数字之间的差距随着绝对值的增加而增加。
考虑这个代码:
#include <cmath>
#include <iostream>
#include <limits>
void foo(float x, int n)
{
while (n-- > 0)
{
std::cout << x << "\n "[n > 0];
x = std::nextafter(x, std::numeric_limits<float>::infinity());
}
}
int main()
{
std::cout.precision(1000);
foo(0.001, 3);
foo(1, 3);
foo(100000000, 3);
}
Run Code Online (Sandbox Code Playgroud)
它float以尽可能慢的速度迭代这些值,即以尽可能小的数量递增值。
0.001000000047497451305389404296875 0.00100000016391277313232421875 0.001000000280328094959259033203125
1 1.00000011920928955078125 1.0000002384185791015625
100000000 100000008 100000016
Run Code Online (Sandbox Code Playgroud)
如您所见,在100000000它附近只能表示每 8 个整数。