首页 > 解决方案 > 有效地从 32 位数据类型中删除 2 位

问题描述

假设您有 32 位数据类型:

// The letters are just to identify the position of each bit later in the post
abcdefgh ijklmnop qrstuvwx yzABCDEF

我正在记录在某些位置“丢弃”位的最有效方法,其中丢弃意味着“删除”给定位,并移动以下位以填充其位置。

示例:假设我想删除位“a”和“q”。然后结果应该看起来像:

bcdefghi jklmnopr stuvwxyz ABCDEF00

或者

00bcdefg hijklmno prstuvwx yzABCDEF

任何一个结果都是可以接受的。

在我的具体情况下,我还可以施加以下约束:

目前我正在使用这样的方法(伪代码):

// called with number = abcdefgh ijklmnop qrstuvwx yzABCDEF
auto drop_bits_1_16(unsigned int number)
{
    number = number << 1; // number becomes: bcdefghi jklmnopq rstuvwxy zABCDEF0
    unsigned number1 = number & 0xFFFE0000;  // number1 comes: bcdefghi jklmnop0 00000000 00000000

    unsigned number2 = number & 0x0000FFFF; // number2 becomes: 00000000 00000000 rstuvwxy zABCDEF0
    number2 = number2 << 1;  // number2 becomes: 00000000 0000000r stuvwxyz ABCDEF00

    return number1 | number2;  // returns bcdefghi jklmnopr stuvwxyz ABCDEF00
}

但我想知道那里是否有更聪明/更有效的方法?

标签: c++algorithmbit-manipulation

解决方案


向右打包比向左打包要容易一些,因为只需要移动 15 位,而不是 15 的两倍。我不知道如何取消屏蔽,所以

((number & 0x7FFF0000) >> 1) | (number & 0x00007FFF)

这不需要丢弃的位为零。有四次按位运算,越少就会困难。


三个操作有一个方法!

添加 15 个低位以将它们左移一位(乘以 2),然后将整体右移。

(number + (number & 0x7FFF)) >> 1

注意:第 15 位必须为零。

也许下面的表达式会给编译器一些更好的代码生成选项:

(number + (unsigned short)number) >> 1

我应该补充一点,其他最终布局也是可能的吗?

(number + (unsigned short)number) << 1

推荐阅读