如何访问位集中的位范围?
How to access range of bits in a bitset?
我有一个非常大的比特集,比如说 100 亿比特。
我想做的是将其写入文件。但是,使用 .to_string()
实际上会冻结我的计算机。
我想做的是遍历位并一次取 64 位,将其转换为 uint64
,然后将其写入文件。
但是我不知道如何访问位集的不同范围。我该怎么做?我是 c++ 的新手,不确定如何访问底层 bitset::reference 所以请提供一个示例作为答案。
我尝试使用指针,但没有达到我的预期。这是我目前正在尝试的示例。
#include <iostream>
#include <bitset>
#include <cstring>
using namespace std;
int main()
{
bitset<50> bit_array(302332342342342323);
cout<<bit_array << "\n";
bitset<50>* p;
p = &bit_array;
p++;
int some_int;
memcpy(&some_int, p , 2);
cout << &bit_array << "\n";
cout << &p << "\n";
cout << some_int << "\n";
return 0;
}
输出
10000110011010100111011101011011010101011010110011
0x7ffe8aa2b090
0x7ffe8aa2b098
17736
每个 运行 的最后一个数字似乎都在变化,这不是我所期望的。
程序中有几个错误。 bitset<50>
可以容纳的最大值是 1125899906842623
,这比 bit_array
在程序中初始化的值小得多。
some_int
必须定义为 unsigned long
并验证 unsigned long
在您的平台上是否有 64 位。
之后,循环测试bit_array
的每一位,然后进行适当的按位运算(或和移位)并将结果存储到some_int
。
std::size_t start_bit = 0;
std::size_t end_bit = 64;
for (std::size_t i = start_bit; i < end_bit; i++) {
if (bit_array[i])
some_int |= mask;
mask <<= 1;
}
您可以在浏览大型位集时适当地更改 start_bit
和 end_bit
的值。
见DEMO。
要访问 bitset
的范围,您应该查看提供的接口。缺少 bitset::data()
表示您应该 而不是 尝试直接访问基础数据。这样做,即使它看起来有效,也是脆弱的、hacky 的,并且可能是某种未定义的行为。
我看到将大量 bitset
转换为更易于管理的部分的两种可能性。一种相当直接的方法是逐位处理并将它们收集到某种整数中(或者如果你不是,则将它们直接写入文件 '0'
或 '1'
关心文件大小)。看起来 P.W 已经为此提供了代码,所以我现在将跳过示例。
第二种可能是使用按位运算符和to_ullong()
。这种方法的缺点是它名义上使用辅助存储 space,特别是两个与原始大小相同的附加位集。不过,我说 "nominally",因为编译器可能足够聪明,可以优化它们。可能。也许不吧。而且您正在处理每个超过 1 GB 的大小。实际上,逐位方法可能是要走的路,但我认为这个例子在理论上很有趣。
#include <iostream>
#include <iomanip>
#include <bitset>
#include <cstdint>
using namespace std;
constexpr size_t FULL_SIZE = 120; // Some large number
constexpr size_t CHUNK_SIZE = 64; // Currently the mask assumes 64. Otherwise, this code just
// assumes CHUNK_SIZE is nonzero and at most the number of
// bits in long long (which is at least 64).
int main()
{
// Generate some large bitset. This is just test data, so don't read too much into this.
bitset<FULL_SIZE> bit_array(302332342342342323);
bit_array |= bit_array << (FULL_SIZE/2);
cout << "Source: " << bit_array << "\n";
// The mask avoids overflow in to_ullong().
// The mask should be have exactly its CHUNK_SIZE low-order bits set.
// As long as we're dealing with 64-bit chunks, there's a handy constant to handle this.
constexpr bitset<FULL_SIZE> mask64(UINT64_MAX);
cout << "Mask: " << mask64 << "\n";
// Extract chunks.
const size_t num_chunks = (FULL_SIZE + CHUNK_SIZE - 1)/CHUNK_SIZE; // Round up.
for ( size_t i = 0; i < num_chunks; ++i ) {
// Extract the next CHUNK_SIZE bits, then convert to an integer.
const bitset<FULL_SIZE> chunk_set{(bit_array >> (CHUNK_SIZE * i)) & mask64};
unsigned long long chunk_val = chunk_set.to_ullong();
// NOTE: as long as CHUNK_SIZE <= 64, chunk_val can be converted safely to the desired uint64_t.
cout << "Chunk " << dec << i << ": 0x" << hex << setfill('0') << setw(16) << chunk_val << "\n";
}
return 0;
}
输出:
Source: 010000110010000110011010100111011101011011010101011010110011010000110010000110011010100111011101011011010101011010110011
Mask: 000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
Chunk 0: 0x343219a9dd6d56b3
Chunk 1: 0x0043219a9dd6d56b
我有一个非常大的比特集,比如说 100 亿比特。
我想做的是将其写入文件。但是,使用 .to_string()
实际上会冻结我的计算机。
我想做的是遍历位并一次取 64 位,将其转换为 uint64
,然后将其写入文件。
但是我不知道如何访问位集的不同范围。我该怎么做?我是 c++ 的新手,不确定如何访问底层 bitset::reference 所以请提供一个示例作为答案。
我尝试使用指针,但没有达到我的预期。这是我目前正在尝试的示例。
#include <iostream>
#include <bitset>
#include <cstring>
using namespace std;
int main()
{
bitset<50> bit_array(302332342342342323);
cout<<bit_array << "\n";
bitset<50>* p;
p = &bit_array;
p++;
int some_int;
memcpy(&some_int, p , 2);
cout << &bit_array << "\n";
cout << &p << "\n";
cout << some_int << "\n";
return 0;
}
输出
10000110011010100111011101011011010101011010110011
0x7ffe8aa2b090
0x7ffe8aa2b098
17736
每个 运行 的最后一个数字似乎都在变化,这不是我所期望的。
程序中有几个错误。 bitset<50>
可以容纳的最大值是 1125899906842623
,这比 bit_array
在程序中初始化的值小得多。
some_int
必须定义为 unsigned long
并验证 unsigned long
在您的平台上是否有 64 位。
之后,循环测试bit_array
的每一位,然后进行适当的按位运算(或和移位)并将结果存储到some_int
。
std::size_t start_bit = 0;
std::size_t end_bit = 64;
for (std::size_t i = start_bit; i < end_bit; i++) {
if (bit_array[i])
some_int |= mask;
mask <<= 1;
}
您可以在浏览大型位集时适当地更改 start_bit
和 end_bit
的值。
见DEMO。
要访问 bitset
的范围,您应该查看提供的接口。缺少 表示您应该 而不是 尝试直接访问基础数据。这样做,即使它看起来有效,也是脆弱的、hacky 的,并且可能是某种未定义的行为。bitset::data()
我看到将大量 bitset
转换为更易于管理的部分的两种可能性。一种相当直接的方法是逐位处理并将它们收集到某种整数中(或者如果你不是,则将它们直接写入文件 '0'
或 '1'
关心文件大小)。看起来 P.W 已经为此提供了代码,所以我现在将跳过示例。
第二种可能是使用按位运算符和to_ullong()
。这种方法的缺点是它名义上使用辅助存储 space,特别是两个与原始大小相同的附加位集。不过,我说 "nominally",因为编译器可能足够聪明,可以优化它们。可能。也许不吧。而且您正在处理每个超过 1 GB 的大小。实际上,逐位方法可能是要走的路,但我认为这个例子在理论上很有趣。
#include <iostream>
#include <iomanip>
#include <bitset>
#include <cstdint>
using namespace std;
constexpr size_t FULL_SIZE = 120; // Some large number
constexpr size_t CHUNK_SIZE = 64; // Currently the mask assumes 64. Otherwise, this code just
// assumes CHUNK_SIZE is nonzero and at most the number of
// bits in long long (which is at least 64).
int main()
{
// Generate some large bitset. This is just test data, so don't read too much into this.
bitset<FULL_SIZE> bit_array(302332342342342323);
bit_array |= bit_array << (FULL_SIZE/2);
cout << "Source: " << bit_array << "\n";
// The mask avoids overflow in to_ullong().
// The mask should be have exactly its CHUNK_SIZE low-order bits set.
// As long as we're dealing with 64-bit chunks, there's a handy constant to handle this.
constexpr bitset<FULL_SIZE> mask64(UINT64_MAX);
cout << "Mask: " << mask64 << "\n";
// Extract chunks.
const size_t num_chunks = (FULL_SIZE + CHUNK_SIZE - 1)/CHUNK_SIZE; // Round up.
for ( size_t i = 0; i < num_chunks; ++i ) {
// Extract the next CHUNK_SIZE bits, then convert to an integer.
const bitset<FULL_SIZE> chunk_set{(bit_array >> (CHUNK_SIZE * i)) & mask64};
unsigned long long chunk_val = chunk_set.to_ullong();
// NOTE: as long as CHUNK_SIZE <= 64, chunk_val can be converted safely to the desired uint64_t.
cout << "Chunk " << dec << i << ": 0x" << hex << setfill('0') << setw(16) << chunk_val << "\n";
}
return 0;
}
输出:
Source: 010000110010000110011010100111011101011011010101011010110011010000110010000110011010100111011101011011010101011010110011
Mask: 000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
Chunk 0: 0x343219a9dd6d56b3
Chunk 1: 0x0043219a9dd6d56b