【问题标题】:bitwise most significant set bit按位最高有效设置位
【发布时间】:2012-02-02 18:24:42
【问题描述】:

我想找到设置为1 的最高有效位。我已经尝试了从& 到从1 到31 的所有位的所有可能的方法,但它不起作用。

如果1000000 我想要7。

【问题讨论】:

  • 您详细尝试了什么?结果如何?
  • 我做了所有的计数 += 1&(~x >> 1-31);它给了我与我预期的不同的数字,我想要的最重要的位是 1,就是这样
  • 负数应该如何处理?
  • 没关系,我需要最重要的位,即 1。所以即使我有 -2 我仍然需要 1 的最重要位

标签: java bit-manipulation


【解决方案1】:

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Integer.html#numberOfLeadingZeros%28int%29 你想要32 - Integer.numberOfLeadingZeros(value)之类的东西。

【讨论】:

    【解决方案2】:

    我遇到过的最巧妙的实现 - 三个迭代和一个表查找。

    unsigned int msb32(unsigned int x)
    {
        static const unsigned int bval[] =
        { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };
    
        unsigned int base = 0;
        if (x & 0xFFFF0000) { base += 32/2; x >>= 32/2; }
        if (x & 0x0000FF00) { base += 32/4; x >>= 32/4; }
        if (x & 0x000000F0) { base += 32/8; x >>= 32/8; }
        return base + bval[x];
    }
    

    【讨论】:

      【解决方案3】:

      虽然有一个答案被接受,但我还有另一种我认为更容易分享的方法。

      如果你想使用按位运算,这里是方法。基本上,我将整数右移直到它变为零。不需要面具。

      private static int mostSignificantBit(int myInt){
          int i = 0;
          while (myInt != 0) {
              ++i;
              myInt >>>= 1;
          }
          return i;
      }
      

      另一种方法是数学计算:

      private static int mostSignificantBit(int myInt){
          if (myInt == 0) return 0;    // special handling for 0
          if (myInt < 0) return 32;    // special handling for -ve
      
          return (int)(Math.log(myInt)/Math.log(2)) +1;
      }
      

      【讨论】:

        【解决方案4】:

        如果你坚持直接使用位运算符,你可以试试这样:

        private int mostSignificantBit(int myInt){
          int mask = 1 << 31;
          for(int bitIndex = 31; bitIndex >= 0; bitIndex--){
            if((myInt & mask) != 0){
              return bitIndex;
            }
            mask >>>= 1;
          }
          return -1;
        }
        

        我们将掩码初始化为1 &lt;&lt; 31,因为它表示一个 1 后跟 31 个 0。我们使用该值来测试索引 31(第 32 位)是否为 1。当我们 and 这个值与 myInt 时,除非在 myInt 中设置相应的位,否则我们得到一个 0。如果是这种情况,我们将返回 bitIndex。如果不是,那么我们将掩码向右移动 1 并重试。我们重复,直到我们用完移位的地方,在这种情况下,这意味着没有设置任何位(也许你想在这里抛出异常而不是返回 -1)。

        请注意,这将为1 返回值0,为64 返回值6(二进制中的1000000)。如果您愿意,可以调整它。另请注意,我使用了无符号右移运算符而不是有符号右移。这是因为这里的目的是处理原始位而不是它们的符号解释,但在这种情况下并不重要,因为所有负值都将在移位发生之前的循环的第一次迭代中终止。

        【讨论】:

        • 其实无符号右移运算符的使用很重要。如果myInt不是负数,那么您需要转移mask,它以负值开始。
        • 你是对的,如果使用带符号的右移,mask 将始终有一个不属于的前导 1(因为mask 开始为负数)。但是,这不会影响我的实现结果,因为当myInt 不是负数时,多余的 1 位总是带有 0 的anded(即myInt 的符号位,我们刚才说的是积极)。
        • 好点!我还没有解决在mask 中出现前导 1 的后果,这(正如您所指出的)完全没有。
        【解决方案5】:

        逐次逼近将迭代最小化为五个循环:

        unsigned int mostSignificantBit(uint32_t val) {
          unsigned int bit = 0;
        
          /* 4 = log(sizeof(val) * 8) / log(2) - 1 */
          for(int r = 4; r >= 0 ; --r) {
            unsigned shift = 1 << r; /* 2^r */
            uint32_t sval = val >> shift;
            if (sval) {
                bit += shift;
                val = sval;
            }
          }
          return bit;
        }
        

        【讨论】:

          【解决方案6】:

          也许不是最有效的,但这应该可行::

          public int firstBit(int i) {
              return i < 0 ? 31 : i == 0 ? 0 : Integer.toString(i, 2).length();
          }
          

          【讨论】:

          • 不...只是不。是的,它有效,但哎哟,这太浪费了。
          【解决方案7】:

          只是添加另一种方法

          public static int mostSignificantBit(int b) {
              for (int i = 1 << 30, j = 0; i > 0; i /= 2, j++) {
                     if ((b & i) > 0) {
                      return 31-j;
                  }
              }
              return -1;
          }
          

          【讨论】:

          • 您可能想输入int 而不是byte。
          • 我不认为你的出发点是正确的。这段代码对Integer.MAX_VALUE 给出的答案与对负数的答案相同。
          【解决方案8】:

          只需使用 Long 或 Integer 类的 numberOfTrailingZeros(value) 方法即可。

          【讨论】:

            【解决方案9】:

            对于小端格式:

            ((yourByte & yourBitMask) >> msbIndex) && 0x01
            

            【讨论】:

              【解决方案10】:
              if( value | 0x40 ) return 7;
              else if( value | 0x20 ) return 6;
              else if( value | 0x10 ) return 5;
              else if( value | 0x8 ) return 4;
              else if( value | 0x4 ) return 3;
              else if( value | 0x2 ) return 2;
              else if( value | 0x1 ) return 1;
              

              【讨论】:

              • 返回 8 到 31 发生了什么?
              猜你喜欢
              • 2015-09-22
              • 2011-05-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-10-19
              • 2017-11-18
              • 2015-03-25
              • 1970-01-01
              相关资源
              最近更新 更多