2

在我围绕这个美丽事物的广阔而危险的位面进行的无尽旅程中,The Internet我遇到了一位神秘的、年迈的、白胡子的巫师,他的名字不能被提及。尽管非常强大,但死亡很快就把他带走了。

就在他咽下最后一口气之前,他递给我一个卷轴,一边昏倒一边低声说

Take this and spread the knowledge

在他死后不久,他的身体就变成了能量,纯粹的能量传遍了整个宇宙。

卷轴包含这段代码:

#include <iostream>
int main()
{
    int x = 3;
    while(2 <= x <= 5)
        std::cout << x++;
}

直到今天,谜团仍然存在:

条件如何评估?

4

2 回答 2

13

总是为真,因为2<=x要么计算为1要么0,两者都是<=5

所以这实际上是一个无限循环:

while( (2 <= x) <= 5)
    std::cout<<x++;
于 2013-01-15T12:54:54.743 回答
5

好吧,这个卷轴的作者想要表达一个我们称之为链式运算符符号的条件,这在数学中是众所周知的(也许巫师是数学家?):

Let x ∈ ℜ, 2 ≤ x ≤ 5. Then ...

通常,这在 C++、C、Java 和许多其他具有类似表达式评估逻辑的语言中是不可能的。有一些库可以启用这样的功能,但另一方面会引入冗长,因为您必须首先包装其中一个参数。此外,它对于程序员来说不是很可读。

如果您使用向导在此卷轴上所做的语言编写表达式,它将从左到右计算:

while ( (2 <= x) <= 5 )
    ...

总是true, 因为2 <= xtrueor并且分别隐式转换为orfalse的整数值,总是小于或等于.105

为了表达数学家想要的条件,你必须使用语法

while ( (2 <= x) && (x <= 5) )
    ...

或使用实用函数来准确表达这一点:

template<class T>
bool between(const T& arg, const T& min, const T& max) {
    return !(arg < min) && !(max < arg);
}


while ( between(x, 2, 5) )
    ...

请注意我是如何在 中编写条件的between:它只需要实现operator<(T, T),从而简化自定义类型的实现。

于 2013-01-15T13:05:05.627 回答