【问题标题】:Why is modulo 3 inefficient?为什么模3效率低下?
【发布时间】:2014-06-02 21:54:57
【问题描述】:

我有这个代码 here. 这个代码被称为“高效”,因为它比模 3 更有效。

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

【问题讨论】:

  • 你是在说这个问题的评论,上面写着“作弊”吗?
  • 如果以下两个都成立,我会惊呆了(a)x%3==0 还不是最有效的,并且(b)编译器不够聪明,无法将其换成如果不是更快的版本
  • 如果x%3 与您的方法代码在机器级别上的代码相同,我也会感到惊讶。
  • 为了好玩,我刚刚运行了一个快速的微型基准测试,您改进的算法击败 % 的唯一情况是 n == 0... 对于其他 n 值,您的算法稍慢(n = 3) 对于较大的 n 值,要慢 10 倍...
  • 如果您链接的代码是正确的,我会感到惊讶:例如 21 = 0b10101 所以 oddCtr 最终将是 3 而 evenCtr 将是 0。这是否意味着21 不是 3 的倍数???

标签: java operators modulo


【解决方案1】:

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

给定任意数字nn % 2 可以是01,所以您所要做的就是保留最后一位的值。你可以用一个非常简单的二进制 AND 来做到这一点:

n % 2 == n & 1

另一方面,如果您选择n % 3,则所有有效答案都是(二进制)000110。请注意,现在答案跨越两位;但是,并非所有两位数都有效(二进制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】:

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

    DIV 指令(它是有符号数的对应 IDIV) 给出商和余数(模). DIV r16 潜水 32 位 DX:AX 中的数字由 16 位操作数,并将商存储在 AX 和 DX 中的其余部分。

    【讨论】:

      【解决方案3】:

      不做同样的操作吗 下面?

      不,因为代码不正确:输入21 试试,它会返回false。但是21 % 30

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

      【讨论】:

        【解决方案4】:

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

        这是一个证明 http://blog.teamleadnet.com/2012/07/faster-division-and-modulo-operation.html

        即便如此,您也不应该过度优化代码而不是可读性。应该只对关键组件进行优化,并且在一切就绪之后进行优化,并且不仅可以在理论上进行实际测量。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-21
          • 2023-04-04
          • 1970-01-01
          • 2010-10-01
          • 1970-01-01
          • 2013-12-18
          • 1970-01-01
          • 2021-07-31
          相关资源
          最近更新 更多