是& 检查奇数时比 % 更快?
要检查奇数和偶数,最低位检查是否比使用模数更有效?
>>> def isodd(num):
return num & 1 and True or False
>>> isodd(10)
False
>>> isodd(9)
True
To check for odd and even integer, is the lowest bit checking more efficient than using the modulo?
>>> def isodd(num):
return num & 1 and True or False
>>> isodd(10)
False
>>> isodd(9)
True
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
是的。 标准库中的
timeit
模块是您检查这些内容的方式。 例如:如您所见,在我的 (first-day==old==slow;-) Macbook Air 上,
&
解决方案可重复地比%< 快 7 到 18 纳秒/代码> 解决方案。
timeit
不仅告诉您哪个更快,而且还告诉您快了多少(只需运行测试几次),这通常表明它是多么不重要(您真的关心吗? 10 纳秒的差异,当调用函数的开销约为 400 时?!-)...让程序员相信微优化本质上是无关紧要的,这已被证明是一项不可能完成的任务——尽管已经过去了 35 年(计算机在这段时间里)速度提高了几个数量级!)自从 Knuth 写道
正如他所解释的那样,这句话引用自霍尔的一份更古老的声明。 我想每个人都完全相信他们的情况属于剩下的 3%!
因此,我们(特别是 Tim Peters 值得尊敬)没有无休止地重复“没关系”,而是放入了标准 Python 库模块
timeit
,这使得测量此类微量数据变得非常容易。基准,从而至少让一些程序员说服自己,嗯,这个案例确实属于 97% 组!-)Yep. The
timeit
module in the standard library is how you check on those things. E.g:As you see, on my (first-day==old==slow;-) Macbook Air, the
&
solution is repeatably between 7 and 18 nanoseconds faster than the%
solution.timeit
not only tells you what's faster, but by how much (just run the tests a few times), which usually shows how supremely UNimportant it is (do you really care about 10 nanoseconds' difference, when the overhead of calling the function is around 400?!-)...Convincing programmers that micro-optimizations are essentially irrelevant has proven to be an impossible task -- even though it's been 35 years (over which computers have gotten orders of magnitude faster!) since Knuth wrote
which as he explained is a quote from an even older statement from Hoare. I guess everybody's totally convinced that THEIR case falls in the remaining 3%!
So instead of endlessly repeating "it doesn't matter", we (Tim Peters in particular deserves the honors there) put in the standard Python library module
timeit
, that makes it trivially easy to measure such micro-benchmarks and thereby lets at least some programmers convince themselves that, hmmm, this case DOES fall in the 97% group!-)老实说,我认为这并不重要。
第一个问题是可读性。 什么对其他开发人员更有意义? 我个人在检查数字的偶数/奇数时会期望取模。 我预计大多数其他开发人员也会有同样的期望。 通过引入不同的、意想不到的方法,您可能会使代码阅读和维护变得更加困难。
第二个事实是,在执行任一操作时您可能永远不会遇到瓶颈。 我支持优化,但早期优化是在任何语言或环境中都可以做的最糟糕的事情。 如果由于某种原因,确定一个数字是偶数还是奇数成为瓶颈,那么找到解决问题的最快方法。 然而,这让我回到了我的第一点——第一次编写例程时,应该以最易读的方式编写它。
To be totally honest, I don't think it matters.
The first issue is readability. What makes more sense to other developers? I, personally, would expect a modulo when checking the evenness/oddness of a number. I would expect that most other developers would expect the same thing. By introducing a different, and unexpected, method, you might make code reading, and therefore maintenance, more difficult.
The second is just a fact that you probably won't ever have a bottleneck when doing either operation. I'm for optimization, but early optimization is the worst thing you can do in any language or environment. If, for some reason, determining if a number is even or odd is a bottleneck, then find the fastest way of solving the problem. However, this brings me back to my first point - the first time you write a routine, it should be written in the most readable way possible.
您可以获得的最佳优化是不将测试放入函数中。 '
number % 2
' 和 'number & 1' 是检查奇数/偶数的非常常见的方法,经验丰富的程序员会立即识别该模式,并且如果您确实需要它很明显,您可以随时添加注释,例如“# if number is odd, then blah blah blah” 。The best optimization you can get is to not put the test into a function. '
number % 2
' and 'number & 1' are very common ways of checking odd/evenness, experienced programmers will recognize the pattern instantly, and you can always throw in a comment such as '# if number is odd, then blah blah blah' if you really need it to be obvious.“返回 num & 1 和 True 或 False”? 哇! 如果您是速度狂 (1)“return num & 1”(2) 内联它:
if somenumber % 2 == 1
清晰且击败isodd(somenumber)
code> 因为它避免了 Python 函数调用。"return num & 1 and True or False" ? Wah! If you're speed-crazy (1) "return num & 1" (2) inline it:
if somenumber % 2 == 1
is legible AND beatsisodd(somenumber)
because it avoids the Python function call.约翰提出了一个很好的观点。 真正的开销在于函数调用:
有趣的是,这两种方法在没有函数调用的情况下同时执行。
John brings up a good point. The real overhead is in the function call:
Interestingly both methods remore the same time without the function call.
使用Python 3.6,答案是否。 在 2017 MBP 上使用下面的代码表明使用模更快。
给出这个结果:
正如其他答案中所建议的,函数调用是一个很大的开销,但是,删除它表明模数仍然比按位更快,并且在 Python 3.6.1 中:
结果:
奖励:事实证明这需要大约两倍的时间在 Python 2.7 中运行。
Using Python 3.6 the answer is no. Using the code bellow on a 2017 MBP shows that using modulo is faster.
Gives this result:
As suggested in other answers, the function calls is a large overhead, however, removing it shows that modulo is still faster than bitwise and in Python 3.6.1:
Results:
Bonus: it turns out this takes about double the time to run in Python 2.7.
除了邪恶的优化之外,它还消除了每个程序员无需多看就能理解的非常惯用的“var % 2 == 0”。 所以这也违反了蟒蛇的禅宗,而且收获甚微。
此外,为了提高可读性,a = b 和 True 或 False 已被替换为
return True if num & 1 其他错误
Apart from the evil optimization, it takes away the very idiomatic "var % 2 == 0" that every coder understands without looking twice. So this is violates pythons zen as well for very little gain.
Furthermore a = b and True or False has been superseded for better readability by
return True if num & 1 else False
真的很惊讶上面的答案都没有同时进行变量设置(时间文字是不同的故事)和没有函数调用(这显然隐藏了“较低项”)。 卡在 ipython 的 timeit 的时间上,我得到了明显的获胜者 x&1 - 使用 python2.6 的结果更好,约 18%(使用 python3.1 的约 12%)。
在我很旧的机器上:
Was really surprised none of the above answers did both variable setup (timing literal is different story) and no function invocation (which obviously hides "lower terms"). Stuck on that timing from ipython's timeit, where I got clear winner x&1 - better for ~18% using python2.6 (~12% using python3.1).
On my very old machine: