代码之家  ›  专栏  ›  技术社区  ›  Terence Chow

如何访问位集中的位范围?

  •  2
  • Terence Chow  · 技术社区  · 7 年前

    我有一个非常大的位集,比如说,100亿位。

    我想做的是把它写入一个文件。然而使用 .to_string() 实际上我的电脑被冻结了。

    我想做的是迭代这些位,每次取64位,将其转换为 uint64 然后将其写入文件。

    但是,我不知道如何访问不同范围的位集。我该怎么做?我是C++新手,不知道如何访问下面的位集::引用,请提供一个答案的例子。

    我尝试使用指针,但没有达到我的预期。这是我目前正在尝试的一个例子。

    #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
    

    最后一个数字似乎在每次跑步时都会改变,这不是我所期望的。

    2 回复  |  直到 7 年前
        1
  •  4
  •   P.W    7 年前

    bitset<50> 能容纳的是 1125899906842623 这比什么都少 bit_array 已在程序中用初始化。

    some_int unsigned long 并验证 在您的平台上有64位。

    在此之后,测试每一位 位元阵列 一些 .

    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 .

        2
  •  0
  •   JaMiT    7 年前

    用于访问 bitset ,您应该查看提供的接口。缺少类似的东西 bitset::data() 表示您应该

    我认为有两种可能性可以转换一个巨大的 位组 分成更容易管理的部分。一种相当直接的方法是一点一点地遍历,然后将它们收集成某种整数(或者将它们直接写入一个文件,如图所示) '0' '1' 如果您不太关心文件大小)。看起来P.W已经为此提供了代码,所以我现在跳过一个示例。

    第二种可能性是使用位运算符和 to_ullong()

    #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