如何以滑动窗口的方式从std::bitset中读取比特,并将其转换为int?

问题描述 投票:0回答:1

我有 std::bitset,其中第一 n 位被设置为一些值。对于每个 indexstd::bitset我想看 m 位 (m < n)并将其转换为 int. 当 (index + m) > n,我想绕着走。

比如说,因为 n = 6m = 2:

std::bitset<8> my_bits {0b00101101}; // out of 8 bits, first 6 are set
// bit indexes            76543210

对于每一个位子 indexmy_bits 我想每次取2个比特,然后将它们转换为 int:

ind 0: 10 -> 1
ind 1: 01 -> 2
ind 2: 11 -> 3
ind 3: 10 -> 1
ind 4: 01 -> 2
ind 5: 11 -> 3 (wrapped around)

现在我有以下代码,似乎可以工作(运行它 此处). 我正在寻找更优雅的东西。

#include <iostream>
#include <bitset>
#include <cmath>
int main() {
    const std::bitset <8> my_bits {0b00101101};
    int n = 6;
    int m = 2;

    for (int n_ind = 0; n_ind < n; ++n_ind) {

        std::cout << "ind " << n_ind << " -> ";

        int exp_2 = 0;
        int res = 0;
        for (int m_i = 0; m_i < m; ++m_i) {
            int curr_ind = (n_ind + m_i) % n; // % n is for wrap-around
            res += my_bits[curr_ind] * std::pow(2, exp_2);
            exp_2++;
        }

        std::cout << "res: " << res << std::endl;
    }

    return 0;
}

EDIT:我试着写了Sam Varshavchik建议的内容,但似乎没有产生我想要的结果,我做错了什么?另外,我不知道在这种情况下如何实现 "环绕"。

#include <iostream>
#include <bitset>
#include <cmath>

int main() {
    const std::bitset <8> my_bits {0b00101101};
    int n = 6;
    int m = 2;

    unsigned int mask = 0;
    for (int i = 0; i < m; ++i) {
        mask = (mask << 1) + 1;
    }

    int res = 0;
    for (int n_ind = 0; n_ind < n; ++n_ind) {

        int ind_t = n_ind % n;

        res <<= 1;
        res += my_bits[ind_t];
        res &= mask;

        std::cout << "ind " << ind_t << " -> ";
        std::cout << "res: " << res << std::endl;
        std::cout << "res after mask: " << std::bitset<32>(res) << std::endl; 
    }

    return 0;
}
c++ bit-manipulation bitset
1个回答
1
投票

写一个函数。把算法封装起来。将结果累加在一个你会返回的实体中。并使用位移代替 std::pow.

#include <iostream>
#include <bitset>
#include <vector>

template<size_t N>
std::vector<int> convert_bitset_to_ints(const std::bitset<N>& bs, unsigned n, unsigned m) {
    std::vector<int> ret(n);

    for(size_t i = 0; i < n; ++i) {
        for (size_t j = 0; j < m; ++j) {
            ret[i] <<= 1;
            ret[i] |= bs[(i + j) % n];
        }
    }

    return ret;
}

int main() {
    const std::bitset <8> my_bits {0b00101101};
    auto v = convert_bitset_to_ints(my_bits, 6, 2);

    for (auto&& i : v) {
        std::cout << "res=" << i << " mask=" << std::bitset<2>(i) << "\n"; 
    }

    return 0;
}

1
投票

我想展示一个额外的解决方案,基于 std::string.

遗憾的是 std::bitset 不是那么强大,提供的功能也不多。但是,它至少有一个转换功能,以生成一个 std::string. 请看 此处.

有了这些,我们马上就有了需要的功能。所以,首先我们将构建一个字符串(使用 构造者3号)与所需的二进制数字。为了处理环绕的问题,我们将简单地添加两次相同的字符串。然后将 0b101101 的结果将是 "101101101101"。

对于结果,我们只是简单地对原始的子串进行迭代。

请看下面的例子。

#include <iostream>
#include <bitset>
#include <string>

// Programm parameters
constexpr size_t NumberOfBits = 8U;
constexpr size_t n = 6;
constexpr size_t m = 2;

int main() {

    // The test data
    const std::bitset <NumberOfBits> myBits{ 0b00101101 };

    // Convert to binary string
    const std::string s(myBits.to_string(), NumberOfBits - n, n);

    // For easier handling of wrap-arounds we concatenate the string with itself --> 101101101101
    const std::string bitString = s + s;

    // Iterate over m-wide substrings and show converted result
    for (size_t i{}; i < n; ++i)
        std::cout << i + 1 << ".\t" << bitString.substr(i, m) << " --> " << std::stoul(bitString.substr(i, m), nullptr, 2) << '\n';

    return 0;
}

这很优雅,但速度不快。如果你想转换数十亿的数据,我会实现不同的算法,而不使用 std::bitset

© www.soinside.com 2019 - 2024. All rights reserved.