这是一位高级经理在面试时问的问题。

哪个更快?

while(1) {
    // Some code
}

or

while(2) {
    //Some code
}

我说过两者具有相同的执行速度,因为while中的表达式最终应求值为true或false。在这种情况下,两者都求值为true,并且while条件中没有额外的条件指令。因此,两者将具有相同的执行速度,我更喜欢while(1)。

但面试官自信地说: “检查你的基本知识。While(1)比While(2)快。” (他不是在试探我的信心)

这是真的吗?

请参见:“for(;;)”是否比“while (TRUE)”快?如果不是,人们为什么要使用它?


当前回答

对这个问题最有可能的解释是,面试官认为处理器会逐一检查数字的每一位,直到它达到一个非零值:

1 = 00000001
2 = 00000010

如果“is 0 ?”算法从数字的右侧开始,并且必须检查每一位直到它达到非零位,那么while(1){}循环每次迭代必须检查的比特数是while(2){}循环的两倍。

这需要一个关于计算机如何工作的非常错误的思维模型,但它确实有自己的内部逻辑。一种检查方法是询问while(-1){}或while(3){}是否同样快,或者while(32){}是否更慢。

其他回答

这里有一个问题:如果您实际编写一个程序并测量它的速度,两个循环的速度可能是不同的!以下是一些合理的比较:

unsigned long i = 0;
while (1) { if (++i == 1000000000) break; }

unsigned long i = 0;
while (2) { if (++i == 1000000000) break; }

添加了一些打印时间的代码后,一些随机的效果(比如循环在一条或两条缓存线中的位置)可能会产生影响。一个循环可能完全位于一条缓存线内,或者位于一条缓存线的开头,或者它可能横跨两条缓存线。因此,面试官说最快的可能真的是最快的——纯属巧合。

最坏的情况:优化编译器不知道循环做了什么,但知道执行第二个循环时产生的值与第一个循环产生的值相同。并为第一个循环生成完整代码,但不为第二个循环生成完整代码。

对这个问题最有可能的解释是,面试官认为处理器会逐一检查数字的每一位,直到它达到一个非零值:

1 = 00000001
2 = 00000010

如果“is 0 ?”算法从数字的右侧开始,并且必须检查每一位直到它达到非零位,那么while(1){}循环每次迭代必须检查的比特数是while(2){}循环的两倍。

这需要一个关于计算机如何工作的非常错误的思维模型,但它确实有自己的内部逻辑。一种检查方法是询问while(-1){}或while(3){}是否同样快,或者while(32){}是否更慢。

我能想到为什么while(2)会更慢的唯一原因是:

代码将循环优化为 2 . CMP eax 当减法发生时,你实际上是在减法 A. 00000000 - 00000010 CMP eax, 2 而不是 B. 00000000 - 00000001 CMP eax, 1

CMP只设置标志,不设置结果。所以对于最低有效位,我们知道b是否需要借位,而对于a,你必须做两次减法才能得到借位。

我认为线索可以从“高级经理的询问”中找到。这个人显然在成为经理后就停止了编程,然后他/她花了几年时间才成为高级经理。从未失去对编程的兴趣,但从那以后再也没有写过一行字。所以他提到的并不是“任何一个像样的编译器”,而是“这个人在二三十年前合作过的编译器”。

At that time, programmers spent a considerable percentage of their time trying out various methods for making their code faster and more efficient as CPU time of 'the central minicomputer' was so valueable. As did people writing compilers. I'm guessing that the one-and-only compiler his company made available at that time optimized on the basis of 'frequently encountered statements that can be optimized' and took a bit of a shortcut when encountering a while(1) and evaluated everything else, including a while(2). Having had such an experience could explain his position and his confidence in it.

让你被录用的最好方法可能是,在你顺利地引导他进入下一个面试主题之前,让高级经理忘乎所以地给你讲2-3分钟“编程的美好时光”。(好的时机在这里很重要——太快你会打断故事——太慢你会被贴上焦点不集中的标签)。一定要在面试结束时告诉他,你对这个话题非常感兴趣。

根据人们花费在测试、证明和回答这个非常直接的问题上的时间和精力来判断,我认为这两者都因为提出这个问题而变得非常缓慢。

所以花更多的时间在这上面…

虽然(2)很荒谬,因为,

While(1)和While (true)在历史上被用于创建一个无限循环,该循环预计在循环中的某个阶段根据一定会发生的条件调用break。

1只是为了总是求值为真,因此,说while(2)和说while(1 + 1 == 2)一样愚蠢,后者也会求值为真。

如果你想完全傻一点,就用:-

while (1 + 5 - 2 - (1 * 3) == 0.5 - 4 + ((9 * 2) / 4.0)) {
    if (succeed())
        break;
}

我认为面试官犯了一个错别字,这并不影响代码的运行,但如果他故意使用2只是为了表现得奇怪,那么在他把奇怪的语句贯穿你的代码,使其难以阅读和使用之前解雇他。