【问题标题】:C: Setting the i'th bit of an integer to 1 in O(1) [duplicate]C:在O(1)中将整数的第i位设置为1 [重复]
【发布时间】:2017-02-23 13:30:05
【问题描述】:

现在,我知道设置数字的第 i 位的方法是使用移位运算符将 1 移到所需的位,然后将其与数字直接或。 但是这个过程是 O(数字长度),因为将数字移动到第 i 个位置就像遍历直到那里,对吧? 如果我错了,请纠正我。

这是我的代码:

x = x| (1<<i)

有没有办法在 O(1) 中做到这一点? 换句话说,如何直接访问数字中的位? 我正在考虑数组索引。

【问题讨论】:

  • 我认为你错了。这个操作是 O(1)。
  • 这取决于您的硬件,即 CPU。显示您的代码和相关机器码。但是您可以使用查找表来确保安全(但可能更慢)。
  • n |= 1 &lt;&lt; i,像这样吗?
  • 位移是 O(1),就像加法是 O(1)。将 n 添加到 m 时,您不必增加 m n 次。位移也是如此。
  • 明确的答案本质上是错误的,因为这一切都取决于您对基本操作的定义。当然,可变数量的位移通常被认为是基本的,但它始终是您做出的选择,即使您隐含地这样做。

标签: c bit-manipulation time-complexity bitwise-operators bit


【解决方案1】:

1 移位k 位是在硬件中完成的。在一个非常简化的级别上,n-bit CPU 具有n 寄存器,它们表示在每个方向上移动了 0、1、2、...、n-1 位的数字。当执行移位操作时,CPU根据移位次数将数字加载到寄存器k中,并在下一个周期读取输出。这使得位移成为 O(1) 操作。

This Q&A 的图表解释了使用多路复用器的现代 CPU 的 O(1)“魔力”背后的硬件。

【讨论】:

  • 谢谢!!!但从图中,我推断对于 2^i 位系统,我需要 i 层电路,对吗?因此,对于给定的系统,移位是在恒定时间内完成的。
  • @Tinkidinki 是的,桶形移位器需要i 层用于 2^i 位系统。然而,所有i 层同时处于活动状态,所以即使我们谈论的是i 门延迟,操作也会在一个周期内完成(当然,这比门延迟要长得多)。跨度>
  • 并非所有处理器都有桶形移位器...P4没有。
【解决方案2】:

正如其他人指出的那样,n |= 1 &lt;&lt; i 不是 O(n)。这是因为大多数 CPU 中的位移操作是一条指令,而我目前熟悉的那些指令需要一个或两个 IIRC 周期。

但是,如果您在 C 代码中引入循环,那么这当然是 O(n),例如:

n = 1;
for(j = 0; j < i; ++j)
    n <<= 1;
x |= n;

对于通常在整数值中设置位的重构位设置,您可以执行以下操作:

typedef enum x_bits_e {
    x_bit1 = 1 << 0;
    x_bit2 = 1 << 1;
    x_bit3 = 1 << 2; 
     // and so on
};

int16_t set_bit_in_x(int16 x, x_bits_e i)
{ 
    return x | i;
}

【讨论】:

  • 否决票的任何理由?
  • 没问题。我可以投票给你的答案。:)
  • 我没有,但你可以改进命名方式
  • 哈,谢谢@VladfromMoscow,真的很好奇答案可以如何具体改进
  • P4 没有桶形移位器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
  • 2020-05-24
相关资源
最近更新 更多