如何将整数数组转换为位数组?

How to convert an array of integers into an array of bits?

我想要完成的是遍历 8 个整数的数组并将每个整数转换为 8 位的二进制形式。我还希望将每个整数的 8 位存储到一个大小为 64 的整数数组中。这是我到目前为止所拥有的,但我似乎无法获得正确的数组。

int Data[8] = {0,0,190,42,0,0,2,33};   

int bits[64];

for(int j = 0; j < 64;j++){
  for(int i = 0; i < 8;++i){                                                                

      bits[j+i] = Data[i] & (1 << i) ? 1 : 0;                                                   

   }
} 

我想获得的数组如下。 (每一位都是它自己的元素)

{0000000000000000101111100010101000000000000000000000001000100001}

您必须为 8 个整数中的每一个处理 8 位,这确实给出了 64 位。但是循环应该是:

for(int j = 0; j < 8;j++){   // loop on integers
  for(int i = 0; i < 8;++i){
      bits[8*j+i] = Data[j] & (1 << i) ? 1 : 0;
   }
}
#include <cstdint>

int main()
{
    uint64_t Data[8] = { 0,0,190,42,0,0,2,33 };
    uint64_t bits = 0;

    for (int i = 0; i < 8; i++)
    {
        bits |= ((Data[i] & 0xFF) << (i * 8));
    }
    return 0;
}

尝试这样的操作,一次设置 8 位。

注意:我认为 是最有效的答案,但不是最容易重用的答案。因此,这个答案主要是为了通用,以便它可以与任何大小的数组重用(前提是目标数组足够大)。


您还可以通过 std::bitset 传递每个值,这样您就可以制作更通用的版本。

template<typename FromT, size_t FromSZ, typename ToT, size_t ToSZ>
void convert_to_bits(const FromT (&from_arr)[FromSZ], ToT (&to_arr)[ToSZ]) {
    static_assert(ToSZ >= ((sizeof(FromT) * CHAR_BIT) * FromSZ),
                  "Destination array must have enough elements to contain all bits of source array.");

    // Helper value, will be optimised out.
    constexpr size_t ELEMENT_SIZE = sizeof(FromT) * CHAR_BIT;

    // Handles bit manipulation cleanly.
    std::bitset<ELEMENT_SIZE> temp[FromSZ];

    // Populate temp.
    for (size_t i = 0; i < FromSZ; i++) { temp[i] = from_arr[i]; }

    // Fill destination array, one "row" (value in source array) at a time.
    for (size_t i = 0; i < FromSZ; i++) {
        size_t row = i * ELEMENT_SIZE;
        using std::fill;

        if (temp[i].none()) {
            // Row is all 0s, fill its part of destination array appropriately.
            fill(&to_arr[row], &to_arr[row + (ELEMENT_SIZE - 1)], 0);
        } else if (temp[i].all()) {
            // Row is all 1s, fill its part of destination array appropriately.
            fill(&to_arr[row], &to_arr[row + (ELEMENT_SIZE - 1)], 1);
        } else {
            // Row is mixed, do it one bit at a time.
            for (size_t j = 0; j < ELEMENT_SIZE; j++) {
                to_arr[row + j] = temp[i][j];
            }
        }
    }
}

可用作:

int Data[8] = {0,0,190,42,0,0,2,33};
int bits[8 * (sizeof(int) * CHAR_BIT)] = {0};

convert_to_bits(Data, bits);

实例here.


不过,这通常会比 . To check this, I tested it with this program 稍慢,使用五个版本宏中的每一个编译五次:

[注意:所有比较的版本都是硬编码的 ELEMENT_SIZE == 8,因此我的代码会给出与 Serge 的答案相同的结果,让我可以直接插入他的答案。 static_assert 已从 convert_to_bits() 中删除以适应这一点。]

每个案例都被编译成一个单独的程序,以(希望)最小化缓存,并且 运行 在 TutorialsPoint's online environment1 中 5 次。未指定优化选项。

  • 一次与-DSERGE,Serge的回答。

    sh-4.3$ g++ -DSERGE      main.cpp -std=c++14 -o serge
    
  • 一次使用 -DTHROUGH,用于 convert_to_bits() 的标准用例。

    sh-4.3$ g++ -DTHROUGH    main.cpp -std=c++14 -o through
    
  • 曾经使用 -DDIRECT,用于 convert_to_bits() 的手动内联版本。

    sh-4.3$ g++ -DDIRECT     main.cpp -std=c++14 -o direct
    
  • 一旦使用 -DFASTDIRECT,应该(但可能不会)更有效的手动内联版本。

    sh-4.3$ g++ -DFASTDIRECT main.cpp -std=c++14 -o fastdirect
    
  • 曾经使用 -DNAIVE,对于在适当的时候不使用 std::fill() 的幼稚版本。

    sh-4.3$ g++ -DNAIVE      main.cpp -std=c++14 -o naive
    

平均...

  • serge 花费了 29.4 个刻度。
  • through 花费了 30.8 个刻度。
  • direct 花费了 30.6 个刻度。
  • fastdirect 花费了 32.8 个刻度。
  • naive 花费了 32.4 个刻度。

1:由于他们的 C++ 链接现在对我不起作用,我 技术上 使用了他们的在线 Java 环境。然而,这不是问题,因为它们的 C++ 和 Java 环境都使用相同的沙箱和相同的工具;我注意到的唯一区别是 1) 提供了哪个默认 "Hello World" 程序(可以自由创建和重命名文件),以及 2) "Compile" 和 "Execute" 按钮映射的是什么命令到(可以在菜单中更改)。两种环境都有免费的 GCC 和 Javac,允许从 Bash shell.

轻松执行