好吧,而不是通常的“测量它”,而是一个实际的答案 - 因为那东西实际上是真正有趣的数学。尽管编译器也可以而且可能会这样做(至少现代优化 c++ 编译器,javac 当然不会,而且我不知道 JVM 是否会这样做) - 所以最好检查一下它是否还没有为你。
但了解优化背后的理论仍然很有趣:我将使用汇编,因为我们需要乘法的较高 32 位字。以下内容摘自沃伦关于位摆弄的书:
n 是我们想要取模的输入整数:
li M, 0x55555556 ; load magical number (2^32 + 2) / 3
mulhs q, M, n ; q = higher word of M * n; i.e. q = floor(M*n / 2^32)
shri t, n, 31 ; add 1 to q if it is negative
add q, q, t
这里 q 包含 n / 3 的除数,所以我们照常计算余数:r = n - q*3
数学是有趣的部分 - 乳胶在这里会很酷:
q = 楼层( (2^32+2)/ 3 * (n / 2^32) ) = 楼层( n/3 + 2*n/(3*2^32) )
现在,对于 n = 2^31-1(有符号 32 位整数可能的最大 n),误差项小于 1/3(并且非负),这使得很容易证明结果确实是正确的。对于 n = -2^31,我们在上面进行了 1 的修正,如果您简化它,您会发现误差项始终大于 -1/3,这意味着它也适用于负数。
我将证明与错误项界限留给感兴趣的人 - 这并不难。