【问题标题】:How do I retreive the first bit of a number (or specific bits) without a mask? [closed]如何在没有掩码的情况下检索数字(或特定位)的第一位? [关闭]
【发布时间】:2021-06-23 18:53:47
【问题描述】:

假设我们在 16 位中工作

假设我有一个算法可以从一个非常大的数字列表中检索符号。 我可以做类似的事情

sign=(number>0)-(number<0)

但我想比这更有效率。

整数(或浮点数)的第一位应存储其符号值。我怎么能告诉计算机只检索我的号码的第一位? 我试过这个:

sign=number>>16

这很好用,但我真的想只读取 1 位而不做任何操作。

存储这种类型的数据要容易得多。我们为每个条目执行此代码并将其存储为二进制数。

data= (data<<1) + sign

然而,检索这些数据更加复杂。 假设我想读取我的号码的前 n 位或后 n 位。 我们可以做类似的事情

last_10_bits= number & (0b000001111111111)
first_10_bits= (number & (0b111111111100000))>>5

这很好用,但是如果我想读取每一秒位并将其存储在 8 位中怎么办?

bits_2nd = number % (-0b010101010101010)

这行不通!我的号码中间有一堆零,如果不使用算法,我无法摆脱。做一件很容易的事,这是一条很长的路。

本质上,有没有办法让指针只读取我数据中的特定位? 是否有任何其他语言允许这样做,或者这只能通过编写机器代码来实现? 我知道我想太多了,我实际上并没有为此制定算法,这只是提出难题的一种简单方法。

【问题讨论】:

  • 你想多了。使用掩码,让优化编译器完成它的工作。
  • cpu 操作的是字节,而不是位。所以不,不可能,即使在汇编语言中也不行。你必须掩饰和转移。为了帮助解决这个问题,有一本书叫做 Bit Twiddling Hacks 或类似的东西。
  • 可以使用pext 指令从中间删除零
  • 要获取 16 位数字的符号位,您将使用 number &gt;&gt; 15 而不是 sign=number&gt;&gt;16。如前所述,CPU 无法加载单个位。事实上,像 DEC Alpha 这样的许多 CPU 甚至无法加载小于寄存器大小的值。而且您还必须从 RAM 中加载整个单词。没有办法从中读取一个字节

标签: python c++ optimization bit-manipulation


【解决方案1】:

正如 cmets 中所说,您真的应该让编译器完成其工作并使用掩码。而且,如果您想像上一个示例那样消除间隙,则必须手动移动位。

如果您仍想访问单个位,可以使用位域结构:

struct S {
  unsigned int b : 3; // This field is 3 bits long
  unsigned int c : 1; // This one is a single bit
};

然后您可以访问单个字段:

struct S mystruct;
mystruct.b = ...;
mystruct.c = ...;

(https://en.cppreference.com/w/cpp/language/bit_field)


作为替代方案,您还可以使用 C++ 的std::bitset,它提供了一个很好的接口,您甚至不必手动定义结构。和以前一样,生成的机器代码中仍会出现班次。


这不仅仅是编程语言的问题,而是 CPU 本身的问题。语言或库能够提供的最大功能是在 CPU 需要用来提取各个位的移位和掩码之上提供一个不错的接口

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多