【问题标题】:C/C++ Bit TwiddlingC/C++ 位玩弄
【发布时间】:2010-11-25 08:18:18
【问题描述】:

本着graphics.stanford.edu/~seander/bithacks.html的精神,我需要解决以下问题:

int x; 
int pow2; // always a positive power of 2
int sgn;  // always either 0 or 1
// ...
// ...
if(sgn == 0)
    x -= pow2;
else
    x += pow2;

当然我需要避免条件。到目前为止,我想出的最好的是

x -= (1|(~sgn+1))*pow2

但这涉及到我也想避免的乘法。提前致谢。

编辑:谢谢大家,

x -= (pow2^-sgn) + sgn

似乎可以解决问题!

【问题讨论】:

  • 那么你应该接受答案。
  • 当乘法不是问题时,我们还有:x -= (1-2*sgn)*pow,使用映射0 -> 11 -> -1,等于x -> (1-2x)
  • 再一次,括号! ^ 的优先级低于+,所以`x -= pow2^-sgn + sgn` 是x -= pow2^(-sgn+sgn)x -= pow2

标签: c++ c bit-manipulation


【解决方案1】:

我会试试的

x -= (pow2 ^ (~sgn+1)) + sgn

或者,如 lijie 在 cmets 中所建议的那样

x -= (pow2 ^ -sgn) + sgn

如果sgn0~sgn+1 也是0,所以pow2 ^ (~sgn+1) == pow2。如果sgn1(~sgn+1)0xFFFFFFFF,并且(pow2 ^ (~sgn+1)) + sgn == -pow2

【讨论】:

  • 你可以把~sgn+1改成-sgn
  • 哦,是的。呃^的优先级低于+,所以我建议使用括号。
  • @lijie - C 和 C++ 都没有要求 2s 补码。在某些情况下,出于可移植性的原因,最好使用无符号整数并使用 ~sgn+1 的显式 2s 补码形式。当然,在这种情况下,你会使用 unsigned 来处理所有事情(大整数库会做这种事情)。在这种情况下,为了可移植性的正确性,我会说“必须使用 -sgn”,并尽量避免摆弄比特 - 当然,如果它只是为了娱乐/学习也可以。
  • 注意——即使你的平台 2s-complement(如果不是全部),一些最近的编译器将利用标准语言中的“未定义”进行优化,并生成不符合您期望的代码。
  • @steve314:是的,我同意 2 的补码不是强制性的。但是,整个表达式(不仅仅是~sgn+1 部分)都以 2 的补码为前提(否则,条件不能被替换)。替换的建议是基于“1 操作优于 2 种推理”;求反可能和加法一样快,所以求反是在浪费时间。
【解决方案2】:
mask = sgn - 1; // generate mask: sgn == 0 => mask = -1, sgn == 1 => mask = 0

x = x + (mask & (-pow2)) + (~mask & (pow2)); // use mask to select +/- pow2 for addition

【讨论】:

  • @Sven: 不,& 是位运算符
  • @Sven:不——如果你不相信我,看看编辑历史——有一个|,我用+代替了,但没有条件。
  • @Sven:首先(sgn == 0) 不是一个条件,它是一个(无分支的)test。其次,当我重新阅读问题并看到 sgn 只能取值 0 和 1 时,我把它拿出来,使得 test 操作变得不必要。所以正如我所说,从来没有任何条件,也没有人在玩任何游戏——你只是犯了一个简单的错误。
  • 我称之为模棱两可 - == 通常被称为条件运算符,但显然不是(编辑:本身)选择性执行意义上的条件。
  • @Steve314:任何将== 称为条件运算符的人都是错误的——它的正确名称是等式运算符等于运算符。它当然并不意味着分支,这是在这种情况下性能的主要问题。
【解决方案3】:

在我的头顶:

int subMask = sgn - 1;
x -= pow2 & subMask;
int addMask = -sgn;
x += pow2 & addMask;

不保证它是否有效或是否聪明,这只是我脑海中突然冒出来的一个想法。

编辑:让我们让它的可读性降低一点(也就是更紧凑):

x += (pow2 & -sgn) - (pow2 & (sgn-1)); 

【讨论】:

    【解决方案4】:

    我会更改界面并用左移替换乘法。 (使用指数代替 pow2)

    【讨论】:

      【解决方案5】:

      你可以做类似的事情(来自链接) x += ((pow2 ^ -sgn) + sgn)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-17
        相关资源
        最近更新 更多