如何将整数数组转换为位数组?
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.
轻松执行
我想要完成的是遍历 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.
不过,这通常会比
[注意:所有比较的版本都是硬编码的 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.
轻松执行