在for循环中使用科学记数法

Edm*_*ice 55 c++ loops

我最近遇到了一些代码,它有一个循环的形式

for (int i = 0; i < 1e7; i++){
}
Run Code Online (Sandbox Code Playgroud)

我怀疑这样做的智慧,因为1e7是浮点类型,并且i在评估停止条件时会促使它被提升.这应该引起关注吗?

Bat*_*eba 50

这里房间里大象是a的范围int 可以小到-32767到+32767,并且为此分配比这更大的值的行为int未定义的.

但是,至于你的要点,确实应该关注你,因为这是一个非常坏的习惯.事情可能会出错,1e7是浮点双重类型.

i由于类型提升规则而将转换为浮点的事实有点没有实际意义:如果意外截断明显的整数文字,则会发生真正的损坏.通过"示例证明"的方式,首先考虑循环

for (std::uint64_t i = std::numeric_limits<std::uint64_t>::max() - 1024; i ++< 18446744073709551615ULL; ){
    std::cout << i << "\n";
}
Run Code Online (Sandbox Code Playgroud)

i如您所料,这将输出范围内的每个连续值.注意std::numeric_limits<std::uint64_t>::max()18446744073709551615ULL,这比2的64次方(这里我用幻灯片般的"经营者"少1 ++<一起工作时,这是非常有用unsigned的类型.很多人认为-->,并++<为混淆,但在科学规划,他们是共同的,特别是-->.)

现在在我的机器上,double是一个IEEE754 64位浮点.(例如,方案特别擅长于精确表示2的幂 - IEEE754可以精确地表示2到1022的幂.)因此18,446,744,073,709,551,616(2的64次幂)可以精确地表示为double.之前最接近的可表示数字18,446,744,073,709,550,592(减少1024).

所以现在让我们把循环写成

for (std::uint64_t i = std::numeric_limits<std::uint64_t>::max() - 1024; i ++< 1.8446744073709551615e19; ){
    std::cout << i << "\n";         
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上只输出一个i:( 18,446,744,073,709,550,592我们已经看过的数字).这证明这1.8446744073709551615e19是一种浮点类型.如果允许编译器将文字视为整数类型,则两个循环的输出将是等效的.

  • 是否有人认真地写"i ++ <foo"而不是"i ++ <foo"?我认为这样做的唯一原因是开个玩笑. (19认同)
  • @cat不,'moot'(不是'静音')是正确的说法. (9认同)
  • @DanielFischer我更惊讶的是,人们仍然使用"++"内联,个人而言,更多的是它在某些语言社区中被视为正常.我总是憎恶将变量变异混合到条件中间.= /更糟糕的是`for`语法的最后一部分是为增量明确保留的... (3认同)

Fra*_*fer 14

它会工作,假设你int的至少是32位.

但是,如果你真的想使用指数表示法,最好在循环外定义一个整数常量并使用正确的强制转换,如下所示:

const int MAX_INDEX = static_cast<int>(1.0e7);
...
for (int i = 0; i < MAX_INDEX; i++) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

考虑到这一点,我想说写起来要好得多

const int  MAX_INDEX = 10000000;
Run Code Online (Sandbox Code Playgroud)

或者如果你可以使用C++ 14

const int  MAX_INDEX = 10'000'000;
Run Code Online (Sandbox Code Playgroud)


Che*_*Alf 10

1e7是类型的文字double,通常double是64位IEEE 754格式,带有52位尾数.大致的2每第十功率对应于10的第三功率,所以double应能代表整数高达至少10 5*3 = 10 15,准确.如果int是32位,那么int大约有10 3*3 = 10 9作为最大值(要求谷歌搜索它说"2**31 - 1"= 2 147 483 647,即粗略估计的两倍).

因此,在实践中,它在当前桌面系统和更大的桌面系统上是安全的.

但是C++只允许int16位,而在例如具有那么小的嵌入式系统上,int可能会有未定义的行为.