[英]Why is modulo 3 inefficient?
渐近复杂度显然是相同的(它是恒定时间)。 另一方面,模2很容易以二进制形式实现。 模3稍微复杂一些。
给定任意数字n
, n % 2
可以为0
或1
,因此您要做的就是保留最后一位的值。 您可以使用一个非常简单的二进制AND来执行此操作:
n % 2 == n & 1
在另一方面,如果你做n % 3
,所有有效的答案是(二进制) 00
, 01
和10
。 请注意,现在答案跨越了两位。 但是,并非所有两位数字都是有效的(二进制数11
不能是n % 3
的结果)。 因此,您需要执行额外的操作:
// 3DEC == 11BIN, so (n & 3) keeps the last two bits of n. You
// then have to ensure that these last two bits are not both 1.
n % 3 == n & 3, if (n & 3) != 3
我不知道模数3是如何在硬件中实现的,但是不管模数3是如何实现的,它都将比模数2稍微复杂一些。也就是说,认为您可以进行更有效的模数运算是很愚蠢的在软件中比在硬件中已经可用
在汇编级别,模数是通过指令DIV来实现的,对于指令DIV而言,它的速度可能比使用逻辑运算,移位和分支慢。
DIV指令(和带符号的IDIV的对应IDIV)给出商和余数(模)。 DIV r16通过16位操作数对DX:AX中的32位数字进行潜水,并将商存储在AX中,将余数存储在DX中。
它在下面不执行相同的操作吗?
否,因为代码不正确:使用输入21
尝试,它将返回false
。 但是21 % 3
是0
。
21
是0b10101
。 这意味着在while循环之后,链接算法的oddCtr = 3
, evenCtr = 0
。 因为3 != 0
,算法返回false
。
该Java代码不会转换为相同的机器代码。 移位和与运算比本机代码中的模运算要快。 该示例代码将解析为本机代码,并在每次需要时调用。
这是一个证明http://blog.teamleadnet.com/2012/07/faster-division-and-modulo-operation.html
即使这样,您也不应过度优化代码而不是提高可读性。 仅应在关键组件上进行优化,并且在所有内容都设置好之后,不仅可以从理论上实际评估收益。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.