【问题标题】:How to remove trailing zeros from a binary number如何从二进制数中删除尾随零
【发布时间】:2020-09-25 09:21:48
【问题描述】:

我有一个 long long 类型的整数,我想在删除其二进制表示中存在的该整数的尾随零后将其转换为新整数。

【问题讨论】:

  • 你走了多远?
  • @gmatht 没试过,找到了另一种方法来完成我正在做的任务。无论如何,如果您想出解决方案,请告诉我。谢谢。
  • 如果值为LLONG_MIN,您期望得到什么结果? 1 个?
  • @chux-ReinstateMonica 我不确定。我只是希望删除尾随零,如果它们不存在,则返回原始整数。
  • @pcgamer:问题是您是否希望数字的高位设置为 0 以删除每个尾随 0 位或设置为 1 用于负数,从而保留符号。

标签: c binary bit-manipulation long-integer


【解决方案1】:

这是一种蛮力方法:

long long remove_trailing_zeroes(long long v) {
    if (v != 0) {
        while ((v & 1) == 0)
            v /= 2;
    }
    return v;
}

这是无符号数的直接方法,但除法可能比上述迭代成本更高:

unsigned long long remove_trailing_zeroes(unsigned long long v) {
    if (v != 0) {
        // v and (v - 1) differ only in the trailing 0 bits plus 1
        // shifting v ^ (v - 1) right by 1 and adding 1 gives the power of 2
        // by which to divide v to remove all trailing 0 bits
        v /= (((v ^ (v - 1)) >> 1) + 1);
    }
    return v;
}

harold 建议进行这种简化:

unsigned long long remove_trailing_zeroes(unsigned long long v) {
    if (v != 0) {
        // `-v`, which is `(~v + 1)` has all bits flipped except the least
        // significant 1 bit.
        // dividing v by `-v & v` shifts all trailing zero bits out,
        v /= -v & v;
    }
    return v;
}

可以简化为一个表达式:

unsigned long long remove_trailing_zeroes(unsigned long long v) {
    return v ? v / (-v & v) : v;
}

为避免除法,您可以用一种有效的方法计算v ^ (v - 1) 中的位数,然后将v 右移比该数字少一。这也适用于0,因此您将获得无分支代码。

你可以在Bit Twiddling Hacks的迷人词中找到其他方法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-28
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 1970-01-01
    • 2021-08-12
    • 2016-11-24
    相关资源
    最近更新 更多