【问题标题】:How I can remove all odds bits in C? [closed]如何删除 C 中的所有赔率位? [关闭]
【发布时间】:2017-08-15 14:13:52
【问题描述】:

我有 int 136970250 (1000 0010 1010 0000 0000 0000 1010) -> 我需要删除所有奇数位(1、3、5、7...)

1000 0010 1010 0000 0000 0000 1010 -> 10 0111 0000 0011 (9987) - 因为这些位没有信息。

怎么做?

【问题讨论】:

  • 显示您的尝试以及您的问题到底在哪里
  • 应该是 & 与所有偶数位
  • 所以不仅屏蔽了位,实际上还缩短了位数?您要解决的实际问题是什么?为什么要这样做(实际上是删除位,移动它们以适应较小的数据类型)?用例是什么?
  • 为什么不为 每个字节 创建一个 0xAA 掩码(例如,0xAAAAAAAA 表示 32 位数字),然后与您的 AND原号码? (或者如果它实际上是您想要的 偶数 位,则为每个字节使用 0x55
  • 这怎么“太宽泛”了?这是一个非常具体的问题。

标签: c bit-manipulation bit


【解决方案1】:
  1. 新建一个整数,初始化为0

  2. 使用 for 循环从 0 迭代到原始整数中位数的一半(不包括在内)

  3. 对于循环中的每次运行,将原始整数与(1 << (i * 2)) 相加。如果它不为零,则将新整数或(1 << i)

  4. 结局

编辑:再次查看示例,您实际上 想要的是删除所有 偶数 位,而不是奇数位。因此,只需将步骤 3 中的原始整数与 (1 << (i * 2 + 1)) 相加即可。

编辑 2:从您的示例看来,您正在使用 32 位整数,但只是为了涵盖所有基数,我要补充一点,如果您的整数实际上是 64 位,您应该替换 @987654324 @ 在第 3 步中使用 1ULL

【讨论】:

    【解决方案2】:

    我怎样才能消除所有赔率位...?
    我需要删除所有奇数位(1、3、5、7...)

    考虑到最低有效位通常是位 0,OP 的单个示例看起来像保留奇数位。

    此答案假定代码需要保留偶数位并丢弃奇数位。很容易调整算法以保留其他位。


    分组移位,而不是 32 次迭代的循环。首先配对所需的位,然后以 4 个为一组,然后以 8 个为一组,以此类推。

    假设我们要保留位 0b .a.b .c.d .e.f .g.h .i.j .k.l .m.n .o.p

    uint16_t IK_RemoveOddBits(uint32_t x) {
      // x = 0b .a.b .c.d .e.f .g.h .i.j .k.l .m.n .o.p
    
      x = ((x & 0x44444444) >> 1) | ((x & 0x11111111) >> 0);
      // x = 0b ..ab ..cd ..ef ..gh ..ij ..kl ..mn ..op
    
      x = ((x & 0x30303030) >> 2) | ((x & 0x03030303) >> 0);
      // x = 0b .... abcd .... efgh .... ijkl .... mnop
    
      x = ((x & 0x0F000F00) >> 4) | ((x & 0x000F000F) >> 0);
      // x = 0b .... .... abcd efgh .... .... ijkl mnop
    
      x = ((x & 0x00FF0000) >> 8) | ((x & 0x000000FF) >> 0);
      // x = 0b .... .... .... .... abcd efgh ijkl mnop
    
      return x;
    }
    

    要删除偶数位,请通过添加x >>= 1 或简单地修改上述代码

    uint16_t IK_RemoveEvenBits(uint32_t x) {
      return IK_RemoveOddBits(x >> 1);
    }
    

    提示:最好在编码这些移位类型问题时使用 unsigned 类型。 有符号整数的符号位不需要扩展。

    【讨论】:

      【解决方案3】:

      奇数位可以在几个bit_permute_steps(见下文)中被删除(假设它们被清零),例如:

      x = bit_permute_step(x, 0x22222222, 1);  // Bit index swap 0,1
      x = bit_permute_step(x, 0x0c0c0c0c, 2);  // Bit index swap 1,2
      x = bit_permute_step(x, 0x00f000f0, 4);  // Bit index swap 2,3
      x = bit_permute_step(x, 0x0000ff00, 8);  // Bit index swap 3,4
      

      (由calcperm生成)

      这可以通过扩展常量和添加额外的步骤轻松扩展到 64 位。如果要删除偶数位,可以先右移 1。

      bit_permute_step的定义是

      t_bits bit_permute_step(t_bits x, t_bits m, t_uint shift) {
        t_bits t;
        t = ((x >> shift) ^ x) & m;
        x = (x ^ t) ^ (t << shift);
        return x;
      }
      

      使用合适的类型。

      对于现代 Intel 处理器(和 Ryzen,但那里速度很慢),更内置的解决方案是使用 _pext_u32 并带有您想要保留的所有位的掩码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-03
        • 2013-02-08
        相关资源
        最近更新 更多