我有这段代码here.这段代码被称为“高效”,因为它比模3更有效。
但为什么模3效率低?它下面没有做同样的操作吗? 模数运算的复杂性是什么?
答案 0 :(得分:3)
渐近复杂度显然是相同的(它是恒定时间)。另一方面,模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
我不知道modulo 3是如何在硬件中实现的,但不管它是如何实现的,它都会比模2稍微复杂一点。尽管如此,思考它是愚蠢的您可以在软件中进行比硬件中已有的更高效的模运算。
答案 1 :(得分:2)
在汇编级别中,模数是用指令DIV实现的,对于大数字,它可能比使用逻辑运算,移位和分支慢。
DIV指令(以及签名号码的对应IDIV) 给出商和余数(modulo)。 DIV r16潜水32位 DX中的数字:AX由16位操作数组成,并将商存储在AX和 DX中的剩余部分。
答案 2 :(得分:1)
不执行相同的操作 下方?
不,因为代码不正确:请尝试输入21
,然后返回false
。但21 % 3
为0
。
21
是0b10101
。这意味着链接算法在while循环后具有oddCtr = 3
和evenCtr = 0
。因为3 != 0
算法会返回false
。
答案 3 :(得分:0)
该java代码不会转换为相同的机器代码。 Shift和AND操作比本机代码中的模数更快。示例代码被解析为本机代码,并且每次都需要调用。
这是一个证据 http://blog.teamleadnet.com/2012/07/faster-division-and-modulo-operation.html
即便如此,您也不应过度优化代码而不是可读性。应该只对关键部件进行优化,并且在所有设置完成后,实际上不仅在理论上也可以测量效益。