如何以滑动 window 的方式从 std::bitset 读取位并将它们转换为 int?
How to read bits from std::bitset in a sliding window fashion and convert them to int?
我有 std::bitset
,其中前 n
位设置为某些值。对于 std::bitset
中的每个 index
,我想读取 m
位 (m < n
) 并将它们转换为 int
。 (index + m) > n
的时候,我想环绕
例如,对于n = 6
和m = 2
:
std::bitset<8> my_bits {0b00101101}; // out of 8 bits, first 6 are set
// bit indexes 76543210
对于 my_bits
中的每一位 index
我想一次取 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)
现在我有以下代码,它似乎可以工作(运行 它 here)。我正在寻找更优雅的东西。
#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;
}
编辑:
我试着写下 Sam Varshavchik 的建议,但它似乎没有产生我想要的结果,我做错了什么?另外,我不知道如何在这种情况下实现 "wrap around"。
#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;
}
写一个函数。封装算法。在实体中累积结果 return。并使用移位代替 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;
}
我想展示一个基于 std::string
的附加解决方案。
不幸的是,std::bitset
不是那么强大并且提供的功能不多。但是,它至少有一个转换函数来生成一个std::string
。请参阅 here。
有了它,我们立即拥有了所需的功能。因此,首先我们将使用所需的二进制数字构造一个字符串(使用 constructor number 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
我有 std::bitset
,其中前 n
位设置为某些值。对于 std::bitset
中的每个 index
,我想读取 m
位 (m < n
) 并将它们转换为 int
。 (index + m) > n
的时候,我想环绕
例如,对于n = 6
和m = 2
:
std::bitset<8> my_bits {0b00101101}; // out of 8 bits, first 6 are set
// bit indexes 76543210
对于 my_bits
中的每一位 index
我想一次取 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)
现在我有以下代码,它似乎可以工作(运行 它 here)。我正在寻找更优雅的东西。
#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;
}
编辑: 我试着写下 Sam Varshavchik 的建议,但它似乎没有产生我想要的结果,我做错了什么?另外,我不知道如何在这种情况下实现 "wrap around"。
#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;
}
写一个函数。封装算法。在实体中累积结果 return。并使用移位代替 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;
}
我想展示一个基于 std::string
的附加解决方案。
不幸的是,std::bitset
不是那么强大并且提供的功能不多。但是,它至少有一个转换函数来生成一个std::string
。请参阅 here。
有了它,我们立即拥有了所需的功能。因此,首先我们将使用所需的二进制数字构造一个字符串(使用 constructor number 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