Java 为什么模3是低效的?

Java 为什么模3是低效的?,java,operators,modulo,Java,Operators,Modulo,我有这个代码,这个代码叫做“高效”,因为它比模3更高效 但为什么模3是低效的?它在下面不做同样的操作吗? 模运算的复杂性是什么 在汇编级,模是用指令DIV实现的,对于大的数字,它可能比使用逻辑运算、移位和分支慢 DIV指令(以及签名数字的对应IDIV) 给出商和余数(模)。DIV r16潜水32位 DX:AX中的数字乘以16位操作数,并将商存储在AX和 其余部分用DX表示 在汇编级,模是用指令DIV实现的,对于大的数字,它可能比使用逻辑运算、移位和分支慢 DIV指令(以及签名数字的对应IDIV)

我有这个代码,这个代码叫做“高效”,因为它比模3更高效

但为什么模3是低效的?它在下面不做同样的操作吗?
模运算的复杂性是什么

在汇编级,模是用指令DIV实现的,对于大的数字,它可能比使用逻辑运算、移位和分支慢

DIV指令(以及签名数字的对应IDIV) 给出商和余数(模)。DIV r16潜水32位 DX:AX中的数字乘以16位操作数,并将商存储在AX和 其余部分用DX表示


在汇编级,模是用指令DIV实现的,对于大的数字,它可能比使用逻辑运算、移位和分支慢

DIV指令(以及签名数字的对应IDIV) 给出商和余数(模)。DIV r16潜水32位 DX:AX中的数字乘以16位操作数,并将商存储在AX和 其余部分用DX表示


该java代码不会转换为相同的机器代码。移位和and运算比本机代码中的模运算快。示例代码被解析为本机代码,并在每次需要时调用

这是一个证明


即使如此,您也不应该过度优化代码的可读性。优化应该只在关键组件上进行,并且在一切就绪之后进行,并且不仅在理论上,而且在实践中可以衡量其好处。

java代码不会转换为相同的机器代码。移位和and运算比本机代码中的模运算快。示例代码被解析为本机代码,并在每次需要时调用

这是一个证明


即使如此,您也不应该过度优化代码的可读性。优化只应在关键组件上进行,并且在一切就绪后,不仅在理论上,而且在实践中可以衡量效益。

渐进复杂性显然是相同的(它是恒定时间)。另一方面,模2很容易用二进制实现;模3稍微复杂一些

给定任何数字
n
n%2
可以是
0
1
,因此您所要做的就是保留最后一位的值。您可以使用一个非常简单的二进制文件和:

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是如何在硬件中实现的,但不管它是如何实现的,它都会比模2稍微复杂一些。尽管如此,认为软件中的模运算比硬件中已有的模运算更有效是愚蠢的。

渐近复杂性显然是相同的(它是常数时间)。另一方面,模2很容易用二进制实现;模3稍微复杂一些

给定任何数字
n
n%2
可以是
0
1
,因此您所要做的就是保留最后一位的值。您可以使用一个非常简单的二进制文件和:

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是如何在硬件中实现的,但不管它是如何实现的,它都会比模2稍微复杂一些。也就是说,认为软件中的模运算比硬件中已有的模运算更有效是愚蠢的

它不做同样的操作吗 在下面

否,因为代码不正确:请使用输入尝试它,它将返回
false
。但是
21%3
0

21
0b10101
。这意味着链接算法在while循环之后有
oddCtr=3
evenCtr=0
。因为
3!=0
算法返回
false

它不做同样的操作吗 在下面

否,因为代码不正确:请使用输入尝试它,它将返回
false
。但是
21%3
0


21
0b10101
。这意味着链接算法在while循环之后有
oddCtr=3
evenCtr=0
。因为
3!=0
算法返回
false

你是在谈论关于这个问题的评论,它说这是“作弊”吗?如果以下两个都是真的,我会感到震惊(a)
x%3==0
还不是最有效的(b)编译器不够聪明,如果不是的话,也不足以将它换成更快的版本。如果
x%3
与方法的代码在机器级别上是相同的代码,我也会感到惊讶。为了好玩,我刚刚运行了一个快速的微基准测试,唯一一种改进的算法优于
%
的情况是
n==0
。。。对于n的其他值,对于n的较大值,您的算法会稍微慢一点(n=3)到10倍。如果您链接的代码正确,我将被支持:例如
21=0b10101
,因此
oddCtr
最终将为3,
evenCtr
将为0。这是否意味着21不是3的倍数???你是在谈论关于这个问题的评论,它说这是“作弊”?如果以下两个答案都是正确的,我会感到震惊