【问题标题】:Zip two or more numbers together bitwise将两个或多个数字按位压缩在一起
【发布时间】:2014-01-16 07:07:37
【问题描述】:

在 C/C++/Obj-C 中将两个(或更多)数字的位表示压缩在一起的最佳方法是什么?

我有数字一到三。它们的二进制表示是 [abc, ABC, xyz]。我想用二进制 [aAxbBycCz] 生成一个 num。我主要处理超过 21 位的数字。

(忽略整数、字节序和诸如此类的限制)。

谢谢大家,节日快乐:)

【问题讨论】:

  • 他们的二进制表示怎么可能是abc, ABC, xyz?二进制是01。你到底想做什么?
  • 我认为每个字母a,b,c,A,B,C,x,y,z 都是代表单个位的变量。
  • @self 因为事先不知道每个变量将取哪个值。
  • @Chad 对造成的混乱表示抱歉。我只是想让它们代表未知值。

标签: c math binary


【解决方案1】:

适用于任意位数的解决方案:

const unsigned int BITS = 21;
unsigned int zipper(unsigned a0, unsigned a1, unsigned a2)
{
    unsigned int result = 0;
    for (unsigned int mask = 1<<BITS; mask != 0; mask >>= 1)
    {
        result |= a0 & mask;
        result <<= 1;
        result |= a1 & mask;
        result <<= 1;
        result |= a2 & mask;
    }
    return result;
}

【讨论】:

  • 通过观察,而不是测试:这不需要在循环顶部的初始 result &lt;&lt;= 1; 吗?您正在插入 3 个位,但只为两个留出空间。
  • @Jongware 仔细查看插入位的位置。这项工作是通过在每次迭代结束时对mask 进行位移来完成的。
  • 啊哈。 “最后”位不需要移位,它适合其原始位置。您只需要为两个传入位腾出空间。不错!
【解决方案2】:

如果你需要更快的速度,做一些预先计算:

static unsigned explode[]= { 0, 1, 0x1000, 0x1001, 0x1000000, 0x1000001, 0x1001000, 0x1001001 } ;

unsigned int zipper(unsigned a0, unsigned a1, unsigned a2)
{
  return explode[a0] | ( explode[a1] << 1) | ( explode[a2] << 2 ) ;
}

对于越界等通常的警告。

【讨论】:

  • 不幸的是,我压缩的数字在 0 到 100 万之间(最大 21 位),所以对于小数字来说,这确实是一个非常好的解决方案,但如果我必须这样做,这里就不那么好了制作一个 8MB 的预先计算好的块...
  • @Xrave 请更新您的问题以明确说明您需要一个可扩展到更多位数的解决方案。羊毛之星和我都将您的问题解释为您的输入只有三位。
【解决方案3】:

我会用蛮力做到这一点:

unsigned int binaryZip(unsigned int a0, unsigned int a1, unsigned int a2)
{
    return ((a0 << 0) & 0x001) |
           ((a1 << 1) & 0x002) |
           ((a2 << 2) & 0x004) |
           ((a0 << 2) & 0x008) |
           ((a1 << 3) & 0x010) |
           ((a2 << 4) & 0x020) |
           ((a0 << 4) & 0x040) |
           ((a1 << 5) & 0x080) |
           ((a2 << 6) & 0x100);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    相关资源
    最近更新 更多