【问题标题】:optimized bit manipulation for getting the NOT value优化位操作以获得 NOT 值
【发布时间】:2013-12-17 08:53:48
【问题描述】:

我有一个无符号的 16 位数字 a,我需要获取 ~a 的值。简单地取 ~a 的值是行不通的(对于 a=10,我需要 ~a=5,而不是 ~a=7FF5)。 我能想到的最好的方法是:

int negate(int a)
{
 int mask1 = 0x4000;
 int mask2 = 0x7FFF;

 for (int i=0;i<15;i++)
 {
   if (!(a&mask1))
   {
      mask1>>=1;
      mask2>>=1;
   }
   else
      break;   
 }

 int t = (0x7FFF - ~a) & mask2;

 return t;    
}

这样做的问题是它太慢了;您知道获得所需结果的更快方法吗?

感谢您的帮助

【问题讨论】:

  • 所以只计算有效位?
  • 对于a=5,您会想要2 吗?
  • 是什么让你认为 ~10 应该是 5?
  • ~5 肯定不是 10,除非你说的是小食。但是 10 必须等于 ~~10。因此,~10 不可能是 5。那么......这些数字是什么,肯定不是 int
  • 求输入的 2 的下一个幂,然后与该值减去 1 进行异或?

标签: c++ c optimization bit-manipulation


【解决方案1】:

只是为了验证:您想要的是反转所有位,包括设置的输入的最高有效位,但将所有高于该位的位保留为零?

如果确实如此,那么下面是代码:

// inspired by Hacker's Delight
unsigned significant_bits(unsigned x)
{
    x |= (x >>  1);
    x |= (x >>  2);
    x |= (x >>  4);
    x |= (x >>  8);
    // x |= (x >> 16); // only needed for 32-bit integers
    return x;
}

unsigned negate(unsigned x)
{
    return x ^ significant_bits(x);
}

【讨论】:

  • 我知道 0
  • 如果你调用 hibit(10),在前 4 行之后 x=0x0f;所以我不确定它应该做什么,但它看起来不正确。
  • 对问题的良好解释和很好的答案
  • @Pandrei 你应该打电话给negate,而不是hibit
  • @Pandrei 如果这是您想要的,那么您为什么说您希望 negate(5) 为 10,以上?有了这个解决方案,negate(5) 就会出来 2.
【解决方案2】:

听起来你想要~a &amp; 0xF

【讨论】:

  • 刚刚意识到我可能误解了——a 总是小于 16?
  • 请再次阅读我的问题,数字是 16 位无符号数。
  • @Pandrei 从您的 cmets(~1010 二进制应该是 0101 和 ~0101 应该是 1010)很清楚它大约是 4 位数字,而不是 16 位。如果你执行 Jongware 的解决方案,~0101 不会导致 1010!
【解决方案3】:
 int negate(unsigned int a) {

   if(a==0);
   else if(a==1) a = 0; 
   else if(a<4) a ^= 0x0003;
   else if(a<8) a ^= 0x0007;
   else if(a<16) a ^= 0x000f;
   else if(a<32) a ^= 0x001f;
   else if(a<64) a ^= 0x003f;
   else if(a<128) a ^= 0x007f;
   else if(a<256) a ^= 0x00ff;
   else if(a<512) a ^= 0x01ff;
   else if(a<1024) a ^= 0x03ff;
   else if(a<2048) a ^= 0x07ff;
   else if(a<4096) a^= 0x0fff;
   else if(a<8192) a ^= 0x1fff;
   else if(a<16384) a ^= 0x3fff;
   else if(a<32768) a ^= 0x7fff;
   else a^=0xffff; 
   return a;

 }

 int main()
{

 printf("%d",negate(10));
 return 0;
}

如果您想将大小增加到 32 位数字,您可以添加 else if 分支。第一种情况

  a==0; the result is a itself
  a==1; the result is 0, simple assigning 0 is fine . 

或者很简单,你可以把它放在一个循环中,然后取一个变量,比如i,每次只左移1。然后返回a ^ = (i - 1) ;

【讨论】:

    【解决方案4】:

    通过调用 negate() 传递掩码:

    int negate(int a, int mask)
    {
        return ~a & mask;
    }
    

    执行示例:

    negate(0x000A, 0x000F) == 0x0005
    negate(0x000A, 0x00F0) == 0x00F0
    

    更新:

    int negate(int num)
    {
        unsigned int bitMask = 0xFFFFFFFF;
    
        for(unsigned int bit = 0x80000000; bit != 0; bit >>= 1)
        {
            if(bit & num)
                break;
    
            bitMask /= 2 ;
        }
    
        return ~num & bitMask;
    }
    

    【讨论】:

    • 如果你知道数字就行了,你只知道 0
    • 这与我的算法相同,只是你的算法适用于 32 位值;但我只需要 16 位值。但逻辑和我想的一样。
    • @Pandrei '会出现这样的情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 2015-11-23
    • 2012-08-21
    • 1970-01-01
    • 2017-10-14
    • 1970-01-01
    相关资源
    最近更新 更多