针对奇数进行测试

8

通常使用取模运算符%来检测一个数是偶数还是奇数。

现在我的问题是,使用按位与测试奇数是否有问题,因为检测最右边的位是1还是0比对2进行取模检查更自然。

而且由于32位转换不会改变最右边的位。

以下两个表达式都会得到相同的结果:

(1 + Math.pow(2,52)) & 1 //1

(1 + Math.pow(2,52)) % 2 //1

有理由更喜欢取模运算符而不是位运算符吗?

编辑: 此问题仅适用于64位精度范围内的值,因为只有偶数可以在2^53以上被准确表示,因此两个操作数都会失败(9007199254740993 % 2 //0))。


1
模运算用于计算除法余数,巧合的是,它也可以用作奇偶校验。 - Shark
只要不是在生产代码中,就不要这样做。除非通过分析发现这是瓶颈,并且需要进行性能优化。在代码中加上注释。 - Florian Margaine
2个回答

7
在JavaScript中,使用任何位操作符都会导致数字首先被截断为32位整数。这意味着它对一些较大的值不起作用。(嗯,相当多的较大的值:-)) %运算符不会这样做。
编辑-嘿,你们所有那些给我点赞的好人:等一下 :-) C5H8NNaO4 指出整数截断过程应该保留低位,如果你考虑只是削减尾数的前面部分,这是很合理的;而且一些简单的“测试”表明它似乎工作得很好。
当然,对于实际上非常大的值来说,情况会变得更加复杂,因为在不精确的浮点表示法中表示时可能是奇数还是偶数,因为最低有效数字丢失了。换句话说,在浮点数值中的二进制指数产生一个有效值,其位数超过尾数容量(我认为是53位)时,你要么必须将所有这样的数字视为偶数(因为低位始终为零),要么你必须将问题视为不确定。
显然,我不是一个数学家。

2
对于奇偶校验,转换为32位似乎并不重要,正如OP所说的那样。因此,显然它将适用于大整数值。 - bfavaretto
2
@FrançoisWahl:Crockford声称JavaScript位操作符与硬件“相距甚远”这一说法已经过时。 - T.J. Crowder
@FrançoisWahl 请看T.J.的评论。 - MaxArt
2
@FrançoisWahl:“我本以为书中的信息是基于事实而不仅仅是假设。” Crockford是一个聪明而知识渊博的人,值得一读,但不幸的是,他有时会将自己的观点陈述为事实,这对书籍产生了不利影响(尤其是在继承方面)。但在这种情况下,我认为它只是过时了。它最初是在JavaScript引擎取得重大进展之前出版的,因此其中可能会有偶尔的过时陈述,这些陈述在新版本中还没有被发现。 - T.J. Crowder
3
有时候,看似只需要一杯咖啡就能轻松回答的问题却并不那么简单。 - Pointy
显示剩余10条评论

0

如果你的数字总是可以很好地转换为32位整数,那么位运算似乎会更快--我猜测一些JavaScript引擎可以将其JIT到硬件位运算中。 我构建了一个jsperf来测试它:

http://jsperf.com/evenness

在 Firefox 20 上,我的结果非常不稳定,有时位运算比取模略快,有时则快很多。

如果你的数字可能无法转换为 32 位整数,请坚持使用取模。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接