如何从左到右计算一个字节中连续设置的位的数量,直到第一个 0?

发布于 2024-11-02 23:50:19 字数 524 浏览 0 评论 0原文

我的英语不好,我不能问得更好,但请看下面:

如果二进制中的字节是 1 0 0 0 0 0 0 0 那么结果是 1
如果二进制中的字节是 1 1 0 0 0 0 0 0 那么结果是 2
如果二进制中的字节是 1 1 1 0 0 0 0 0 那么结果是 3
如果二进制中的字节是 1 1 1 1 0 0 0 0 那么结果是 4
如果二进制中的字节是 1 1 1 1 1 0 0 0 那么结果是 5
如果二进制中的字节是 1 1 1 1 1 1 0 0 那么结果是 6
如果二进制中的字节是 1 1 1 1 1 1 1 0 那么结果是 7
如果二进制中的字节是 1 1 1 1 1 1 1 1 那么结果是 8

但是如果例如二进制中的字节是 1 1 1 0 * * * * 那么结果是 3。

我将确定从左边连续设置了多少位通过一次操作向右移动。

结果不一定是 1-8 的数字,只是为了区分。 我认为一两次手术是可能的,但我不知道如何做。

如果你不知道短至 2 个操作的解决方案,请也写下来,我不会再尝试了。

I'm not good in English, I can't ask it better, but please below:

if byte in binary is 1 0 0 0 0 0 0 0 then result is 1
if byte in binary is 1 1 0 0 0 0 0 0 then result is 2
if byte in binary is 1 1 1 0 0 0 0 0 then result is 3
if byte in binary is 1 1 1 1 0 0 0 0 then result is 4
if byte in binary is 1 1 1 1 1 0 0 0 then result is 5
if byte in binary is 1 1 1 1 1 1 0 0 then result is 6
if byte in binary is 1 1 1 1 1 1 1 0 then result is 7
if byte in binary is 1 1 1 1 1 1 1 1 then result is 8

But if for example the byte in binary is 1 1 1 0 * * * * then result is 3.

I would determine how many bit is set contiguous from left to right with one operation.

The results are not necessary numbers from 1-8, just something to distinguish.
I think it's possible in one or two operations, but I don't know how.

If you don't know a solution as short as 2 operations, please write that too, and I won't try it anymore.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

猫烠⑼条掵仅有一顆心 2024-11-09 23:50:19

我能想到的最简单的非分支解决方案:

y=~x
y|=y>>4
y|=y>>2
y|=y>>1

反转 x,并将最左边的 1 位(对应于非反转值中最左边的 0 位)向右扩展。将给出不同的值(虽然不是 1-8,但进行映射非常容易)。

110* ****

变成

001* ****
001* **1*
001* 1*1*
0011 1111

编辑

正如在另一个答案中指出的那样,使用预先计算的查找表可能是最快的。由于只有 8 位,就内存消耗而言甚至可能是可行的。

编辑

嘿,哎呀,我的错..你可以跳过反转,而用 and 代替。

x&=x>>4
x&=x>>2
x&=x>>1

110* ****

您所见

110* **0*
110* 0*0*
1100 0000

,所有以 110 开头的值都会产生相同的输出 (1100 0000)。

编辑:

实际上,“and”版本基于未定义的行为(移动负数),如果使用有符号的8位(即char,而不是C中的unsigned char),通常会做正确的事情),但正如我所说,该行为是未定义的,并且可能并不总是有效。

Easiest non-branching solution I can think of:

y=~x
y|=y>>4
y|=y>>2
y|=y>>1

Invert x, and extend the lefttmost 1-bit (which corresponds to the leftmost 0-bit in the non-inverted value) to the right. Will give distinct values (not 1-8 though, but it's pretty easy to do a mapping).

110* ****

turns into

001* ****
001* **1*
001* 1*1*
0011 1111

EDIT:

As pointed out in a different answer, using a precomputed lookup table is probably the fastets. Given only 8 bits, it's probably even feasible in terms of memory consumption.

EDIT:

Heh, woops, my bad.. You can skip the invert, and do ands instead.

x&=x>>4
x&=x>>2
x&=x>>1

here

110* ****

gives

110* **0*
110* 0*0*
1100 0000

As you can see all values beginning with 110 will result in the same output (1100 0000).

EDIT:

Actually, the 'and' version is based on undefined behavior (shifting negative numbers), and will usually do the right thing if using signed 8-bit (i.e. char, rather than unsigned char in C), but as I said the behavaior is undefined and might not always work.

肥爪爪 2024-11-09 23:50:19

我会支持一个查找表...否则您也可以执行以下操作:

unsigned long inverse_bitscan_reverse(unsigned long value)
{
    unsigned long bsr = 0;
    _BitScanReverse(&bsr, ~value); // x86 bsr instruction
    return bsr;
}

编辑:并不是说您必须小心“值”没有归零位的特殊情况。请参阅 _BitScanReverse 的文档。

I'd second a lookup table... otherwise you can also do something like:

unsigned long inverse_bitscan_reverse(unsigned long value)
{
    unsigned long bsr = 0;
    _BitScanReverse(&bsr, ~value); // x86 bsr instruction
    return bsr;
}

EDIT: Not that you have to be careful of the special case where "value" has no zeroed bits. See the documentation for _BitScanReverse.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文