【问题标题】:A correct way for the integer wrap around?整数环绕的正确方法?
【发布时间】:2019-04-16 16:59:12
【问题描述】:

在 for 循环中确保整数值始终环绕 从 0 到最大 8 的相对更好/更正确的方法是什么? (我使用 32 次迭代,就像这里的示例)我找到了三个选项(A、B 和 C)

例子:

int x = 0;
const int max = 8; // EDIT: Always in the power of two.

for (int i = 0; i < 32; ++i)
{
    // EDIT: "x++;" usage was incorrect here.
    x = i;

//  x = x % max;  // A
//  x &= max - 1; // B
//  x &= ~max;    // C (EDIT: Incorrect, dont use...)

    std::cout << "x: " << x << std::endl;
}

还有其他建议吗?

编辑:性能至关重要,需要最快的解决方案。 我在一些第三方性能关键代码中看到了“x &= ~max”的使用。看起来他们使用这个技巧做了一个环绕。它是否有效或比其他解决方案更快?

谢谢。

【问题讨论】:

  • x %= max 可能是最容易理解的。
  • 你怎么知道它的性能至关重要?你量过吗?直觉就像掷硬币一样可靠,可以猜测哪些代码是关键的,哪些代码不是。
  • 代码“x &= ~max”用于生产就绪的实时代码之一,所以我只是假设有一个原因。

标签: c++ operators bitwise-operators


【解决方案1】:

在这种特殊情况下,B 和 C 都有效,但仅在 max 正好是 2 的幂时才有效。如果不是,%= 将和其他任何东西一样快。

【讨论】:

    【解决方案2】:

    如果 [0,8) 有效并且 max 保证是 2 的幂,x &amp;= (max-1) 有效并且比第一个更快。不能说C。

    【讨论】:

      【解决方案3】:

      对于int,位掩码 (x &amp;= (max-1);) 和取模 (x %= max;) 解决方案会产生不同的汇编,因为它们对负值产生不同的结果。虽然模块解决方案可能更易于阅读,但它的运行速度可能比模块解决方案慢。通常你会使用x %= max;,因为它准确地表达了你想要做的事情,但如果性能至关重要,那么位掩码解决方案值得考虑。

      请注意,对于 unsigned int,gcc 将两种解决方案编译为使用单个 and 指令。

      天箭:https://godbolt.org/z/WAckr7

      【讨论】:

      • 谢谢。我已经更新了我的问题。你对 "x &= ~max" 方法有什么想法吗?
      • 我已经测试过这个方法,它没有问题。我可能需要更多地研究它......
      • @Gediminas 只要值永远不会达到 16,它就可以工作。它只是确保第 4 位始终为 0。
      • 你是对的。我使用“x++;”犯了一个错误在我的测试代码中...这使我的值从 0-7 与“〜max”环绕,所以我很困惑...
      猜你喜欢
      • 2013-01-08
      • 2012-01-08
      • 2023-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多