【问题标题】:Replacing front bits of an int替换int的前位
【发布时间】:2016-12-09 09:50:02
【问题描述】:

替换给定 int 的第一个 x 位:

  1. 要替换的位数
  2. 一个新的位序列

例如: 将前 4 位替换为 5 个 位序列 (1100 -> 10111)

1100 0010 1001 -> 1 0111 0010 1001

我知道如何使用std::bitset 翻转长度相同的位,但如果序列小于或大于第一个序列,我该怎么做?

编辑:为了澄清,我需要用另一个特定数量的位替换一定数量的最高有效位。我不需要算法来检查 int 是否太短而无法替换 4 位,我会处理的。我只需要切断 x 位并连接 y 位,给定一个 int(转换为位)

【问题讨论】:

  • 一个关于术语的小注释:通常位被认为是“第一个”。二进制值通常用左边的最高(或“最后”)位和右边的低位(如普通十进制数)写入。
  • 数字2的前5位是什么?
  • 定义“第一”。
  • 用int代替bitset,可以使用shift right operator >>
  • bitset 和 int 都有固定的位数,但有时不写入前导零。因此,您可能不是用 5 位替换前 4 位,而是将 5 位“01100”替换为其他 5 位:“10111”。

标签: c++ bit-manipulation


【解决方案1】:

要么 first 意味着从被认为是最高有效位 (hsb) 的位序列中的某个位置开始,这意味着必须首先知道在哪里进行操作,并且 first 会改变,因为序列将包含更多或更少的位.
或者 first 表示最低有效位 (lsb),在这种情况下,需要左移/右移来更改要替换的序列,使其具有与新序列相同的大小。

00000100100011101001  
     ^hsb          ^lsb (which is actually first?)

顺便说一句:如果您希望序列在不指定何时构建的情况下增长,您可能需要查看boost.dynamic_bitset

【讨论】:

    【解决方案2】:

    也许你可以....?

    std::size_t x =3113; // which is 1100 0010 1001
    std::size_t y =x%256; // remain of 2^8
    x =y +23 *256; // add 1 0111 0000 0000
    

    【讨论】:

      【解决方案3】:

      我不记得执行此操作所需的 C++ 函数,但我可以编写算法来实现您想要的输出。

      let,
      int x = 0;
      int n = 2; //number of bits to be replaced
      int num = 11010; // 32 bit number to be manipulated with leading 0's
      int unchanged_bits = bit seq length of num - n  
      bit_seq = 101; so 11 will be replaced by 101 and 010 will be unchanged
      
      do left shift x unchanged_bits times and add 1 each time // you will get 111 with leading 0's
      
      now do logical & between num and 111 // you will get num with unchanged bits 010 with leading 0's
      
      now left shift the given bit_seq 3 times// since length of 010 is 3 and you will get 101000
      
      Now do logical OR between 101000 and 010 with leading 0's
      
      Thus you will get desired output

      【讨论】:

        【解决方案4】:

        Result = [ Input-Pattern | Remains-after-MSBs-Trimmed-Out ]

        您可以使用floor(log2(n)) 找到最高设置位(hsb),使用numeric_limits<T>::digits 找到输入数字x 中的位数。

        size_t afterBitPos = floor(log2(x)) - numOfBitsToBeReplaced + 1;
        size_t numberOfBits = (std::numeric_limits<unsigned>::digits - floor(log2(x)) - 1 + numOfBitsToBeReplaced );
        
        //Clear "numberOfBits" MSBs
        x <<= numberOfBits;
        x >>= numberOfBits;
        
        pattern <<= afterBitPos; //Position them in MSB positions.
        
        x = x | pattern;
        

        Live demo.

        【讨论】:

          【解决方案5】:

          如果你想用一些新的位序列new_bits 替换整数n 的前x 位(在我的代码中我使用size_repl 而不是x),你可以使用这个函数(假设函数first_set返回设置的第一位):

          int replace_first_bits(unsigned int n, int size_repl, int new_bits){
              int first = first_set(n);
              if (first < 0){
                  //if no bit is set in n => n = 0 => return new_bits (CHANGE IF NECESSARY)
                  return new_bits; 
              }
          
              //replace bits `first` untill `(first+size-1)` => bits from `first+size` untill last bit stay the same
              int mask_size = (sizeof(unsigned int) << 3) - (first+size_repl);
              if (mask_size < 0){
                  // size_repl is greater than the length of n in binary notation 
                  //     => replace much more than what is used => just replace everything (CHANGE IF NECESSARY)
                  return new_bits;
              }
              int mask = (1 << mask_size) - 1;
              return (new_bits << mask_size) + (n & mask);
          }
          

          我已经像这样实现了first_set

          int first_set(unsigned int i){
              int count = sizeof(unsigned int) << 3;
              unsigned int n = i;
              while(n){
                  n = n >> 1;
                  count--;
              }
              return count;
          }
          

          您可能会注意到我使用了unsigned int 而不是int。这是因为在(有符号的)int 的情况下,如果它是负数,那么第一位将为 1。

          我要补充的另一件事是,我认为最左边的位是第 0 位,最右边的位是第 31 位(对于 32 位整数)。通过使用sizeof(unsigned int),我确信此代码适用于任何大小的int

          Here 是您给出的示例的代码演示:将1100 0010 1001 (= 3113) 的前 4 位替换为 10111 (= 23)。

          希望对你有帮助。

          PS:演示输出中的最后一行帮助我计算位序列中位的索引。

          【讨论】:

            猜你喜欢
            • 2019-11-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-22
            • 2016-06-13
            • 2020-07-04
            • 1970-01-01
            相关资源
            最近更新 更多