最近,我正在阅读Herb Sutter 的 GOTW 的 Double or Nothing的帖子, 我对以下程序的解释感到有些困惑:
int main()
{
double x = 1e8;
while( x > 0 )
{
--x;
}
}
假设这段代码在某台机器上运行 1 秒。我同意这样的代码很愚蠢的观点。
但是,根据有关问题的解释,如果我们x
从更改float
为double
,那么在某些编译器上,它将使计算机永远运行。解释基于标准中的以下引用。
引用 C++ 标准的第 3.9.1/8 节:
有三种浮点类型:float、double 和 long double。double 类型提供的精度至少与 float 一样,long double 类型提供的精度至少与 double 一样。float 类型的值集是 double 类型的值集的子集;double 类型的值集是 long double 类型的值集的子集。
代码的问题是:
如果将“double”更改为“float”,您预计需要多长时间?为什么?
以下是给出的解释:
它可能需要大约 1 秒(在特定的实现中,浮点数可能比双精度更快、一样快或稍慢),或者永远需要,这取决于浮点数是否可以准确地表示从 0 到 1e8 的所有整数值(包括在内)。
标准中的上述引用意味着可能存在可以用双精度表示但不能用浮点表示的值。特别是在一些流行的平台和编译器上,double 可以准确地表示 [0,1e8] 中的所有整数值,但 float 不能。
如果 float 不能准确表示从 0 到 1e8 的所有整数值怎么办?然后修改后的程序将开始倒计时,但最终会达到一个无法表示且 N-1 == N 的值 N(由于浮点精度不足)......和
我的问题是:
如果 float 都不能表示1e8
,那么我们初始化的时候应该已经溢出了float x = 1e8
;那我们怎么能让电脑永远运行呢?
我在这里尝试了一个简单的例子(虽然不是double
但是int
)
#include <iostream>
int main()
{
int a = 4444444444444444444;
std::cout << "a " << a << std::endl;
return 0;
}
It outputs: a -1357789412
这意味着如果编译器无法用int
类型表示给定的数字,则会导致溢出。
那我是不是看错了?我错过了什么?正在x
从更改double
为float
未定义的行为吗?
谢谢!