if(a<901)是否比if(a<=900)快?

与这个简单示例中的情况不同,但循环复杂代码的性能略有变化。我想这需要对生成的机器代码进行一些处理,以防它是真的。


当前回答

只有当制造计算机的人不擅长布尔逻辑的时候。他们不应该这样。

每个比较(>=<=><)都可以以相同的速度进行。

每一次比较都只是一次减法(差值),看看它是正还是负。(如果设置了msb,则数字为负数)

如何检查a>=b?Sub a-b>=0检查a-b是否为正。如何检查a<=b?Sub 0<=b-a检查b-a是否为正。如何检查a<b?Sub a-b<0检查a-b是否为负。如何检查a>b?Sub 0>b-a检查b-a是否为负。

简单地说,对于给定的操作,计算机可以在引擎盖下面执行以下操作:

a>=b==msb(a-b)==0a<=b==msb(b-a)==0a>b==msb(b-a)==1a<b==msb(a-b)==1

当然,计算机实际上也不需要执行==0或==1。对于==0,它可以将电路中的msb反相。

无论如何,他们肯定不会将a>=b计算为a>b||a==b lol

其他回答

它们的速度相同。也许在某些特殊的架构中,他/她所说的是对的,但在x86家族中,至少我知道他们是一样的。因为为此,CPU将执行一个减法(a-b),然后检查标志寄存器的标志。该寄存器的两位被称为ZF(零标志)和SF(符号标志),它在一个周期内完成,因为它将通过一个掩码操作完成。

假设我们讨论的是内部整数类型,不可能一个比另一个更快。它们显然在语义上是相同的。它们都要求编译器做完全相同的事情。只有一个严重损坏的编译器才能为其中一个生成劣质代码。

如果在某些平台上,对于简单整数类型,<比<=快,编译器应始终将常量的<=转换为<。任何没有这样做的编译器都将是一个糟糕的编译器(对于该平台)。

即使有差异,你也不应该注意到。此外,在实践中,除非你要使用一些神奇的常数,否则你必须做一个额外的a+1或a-1来使条件成立,这无论如何都是一个非常糟糕的实践。

仅当计算路径依赖于数据时:

a={1,1,1,1,1000,1,1,1,1}
while (i<=4)
{
     for(j from 0 to a[i]){ do_work(); }
     i++;
}

将计算250倍以上的时间(i<4)

真实世界的例子是计算曼德布洛特集合。如果包含一个迭代1000000次的像素,它将导致延迟,但与<=使用概率的重合度太低。

对于浮点代码,甚至在现代体系结构上,<=比较可能确实会慢一些(一条指令)。这是第一个函数:

int compare_strict(double a, double b) { return a < b; }

在PowerPC上,首先执行浮点比较(更新条件寄存器cr),然后将条件寄存器移动到GPR,将“比较小于”位移位到位,然后返回。它需要四个指令。

现在考虑一下这个函数:

int compare_loose(double a, double b) { return a <= b; }

这需要与上面的compare_strict相同的工作,但现在有两个有趣的位:“小于”和“等于”。这需要一个额外的指令(cror-condition寄存器逐位OR)将这两个位组合为一。因此,compare_sloose需要五条指令,而compare_sstrict需要四条指令。

您可能认为编译器可以这样优化第二个函数:

int compare_loose(double a, double b) { return ! (a > b); }

然而,这将错误地处理NaN。NaN1<=NaN2和NaN1>NaN2都需要评估为假。