Math 如果(n%2==0)或(n&1==0),哪一个查找偶数更快?

Math 如果(n%2==0)或(n&1==0),哪一个查找偶数更快?,math,bit-manipulation,modulo,Math,Bit Manipulation,Modulo,如果n%2==0或ifn&1==0,哪一个更快找到偶数 我希望对那些表达式等效的语言的编译器进行合理的优化,以等效地实现这两个选项 事实上,我尝试过:gcc、clang、MSVC和icc,虽然每个编译器实现的习惯用法都不同于其他编译器1,但四分之三的编译器以相同的方式实现了这两种习惯用法 >只有ICC生成不同的代码,在这种情况下,N& 1==0生成的代码比N% 2=0要好得多,但是您应该考虑ICC错误。 然而,并非所有语言都实现了提前或JIT优化编译器,特别是解释器可能会也可能不会以类似方式优

如果n%2==0或ifn&1==0,哪一个更快找到偶数


我希望对那些表达式等效的语言的编译器进行合理的优化,以等效地实现这两个选项

事实上,我尝试过:gcc、clang、MSVC和icc,虽然每个编译器实现的习惯用法都不同于其他编译器1,但四分之三的编译器以相同的方式实现了这两种习惯用法

<> >只有ICC生成不同的代码,在这种情况下,N& 1==0生成的代码比N% 2=0要好得多,但是您应该考虑ICC错误。

然而,并非所有语言都实现了提前或JIT优化编译器,特别是解释器可能会也可能不会以类似方式优化编译器。如果你对特定的语言或平台感兴趣,你可以考虑标注你的问题来反映。


1对于如此简单的代码,这实际上是令人惊讶和不寻常的。总体而言,clang生成的代码最好,其次是MSVC,然后是gcc。icc为n%2选项生成了非常糟糕的代码。奇怪的是,gcc在-O1生成的代码比在-O2生成的代码要好得多。

这看起来像Python,所以我在Python3.6中尝试过:

from timeit import timeit
a = timeit(stmt='for i in range(100): i%2')
b = timeit(stmt='for i in range(100): i&1')
print(a, b)
时间有点大不相同,谢谢你,垃圾收集器!但一般来说,i%2和i&1的时间分别为4.7秒和6.3秒,我猜这可能不是你所期望的答案


我用dis检查字节码,唯一的区别是一行运行二进制模和二进制模,所以我不确定为什么会有如此大的时间差异。

在任何语言中,它都会产生差异,要求解释器/编译器的实现者退款。使用返回n&1==0替换条件all可以节省更多的时间,以消除分支预测器失败时的任何开销。在任意语言的上下文中,您是否关心这一点,或者只关心Python,或者什么?变化可能更多地与构建范围对象和迭代有关,而不是与垃圾收集器有关。尝试重复5&1和5%2之类的内容,而不是重复整个for循环。但是范围迭代器是以相同的方式为这两个循环创建的,因此它不会对总数产生任何影响。为了确认我用pass语句代替了I%2和I&再次运行了它,两次循环时间都是1.5秒。我只是尝试从命令行用python-m-timeit'5&1'和python-m-timeit'5%2'使用timeit,这两次平均每个循环使用0.0142 usec,最好是100000000个循环中的3个。我颠倒了顺序,得到了完全相同的结果,因此,我认为差异可能在于我们的口译员,而不是操作顺序。出于好奇,如果你使用这个范围,你会得到什么呢?Python 3.5.2产生6.50781165715307 6.241488204104826,Python 2.7.12产生4.794481992721558 4.476944923400879值得注意的是,问题中的原始代码是Python,它是一种解释性语言,因此它可能不会像gcc、clang和,对于C@DillonDavis来说,MSVC是的,我注意到了这一点——这就是为什么我加入了关于优化编译器的警告,这意味着包括运行时优化编译器,例如JIT。然而,我对python解释器不是很熟悉。我知道有几种选择:可以安全地假设像CPython这样的东西通过常量值优化模块?这似乎是一个低垂的果实。因为这个问题没有标记python,也没有提到python,所以我假设一个不涉及语言的答案可能是合适的,不包括所有的实现。我在答案的末尾添加了一个部分,涵盖了这一点,并对另一个答案进行了修改。
from timeit import timeit
a = timeit(stmt='for i in range(100): i%2')
b = timeit(stmt='for i in range(100): i&1')
print(a, b)