Как извлечь подмножество набора битов длиннее, чем unsigned long, без использования to_string или извлечения битов один за другим? - PullRequest
0 голосов
/ 25 января 2020

Я хочу извлечь подмножество из данного набора битов, где:

  1. и G (заданный размер набора битов) и S ( размер подмножества) известны во время компиляции

  2. G > sizeof(unsigned long long) * 8

  3. S <= sizeof(int) * 8

  4. Подмножество может начинаться в любом месте данного набора битов

  5. Полученное подмножество должно быть набором битов правильного размера, S


Я могу выделить подмножество, используя побитовая математика, но тогда bitset.to_ullong не работает из-за ошибки переполнения.

Я знаю, что могу использовать bitset.to_string и выполнять манипуляции / преобразование строк. В настоящее время я занимаюсь извлечением битов один за другим вручную (этого достаточно для моего варианта использования) .

Мне просто интересно узнать, есть ли другие способы делать это.

1 Ответ

1 голос
/ 25 января 2020

std::bitset имеет операторы смещения битов, поэтому, например, вы можете написать функцию для размещения битов (begin,end] спереди:

template <size_t size>
std::bitset<size> extract_bits(std::bitset<size> x,int begin, int end) {
    (x >>= (size-end)) <<= (size-end);
    x <<= begin;
    return x;
}

Например, чтобы получить биты 1 и 2:

int main()
{
    std::bitset<6> x{12};
    std::cout << x << "\n";

    std::cout << extract_bits(x,1,3);
}

Вывод:

001100
010000

Если вы знаете begin и end во время компиляции, вы можете получить std::bitset, содержащий только нужные биты:

template <size_t begin,size_t end,size_t in>
std::bitset<end-begin> crop(const std::bitset<in>& x) {
    return std::bitset<end-begin>{ x.to_string().substr(begin,end-begin) };
};

auto c = crop<1,3>(x);
std::cout << c;        // 01

Если битовый набор слишком велик для unsigned long long, я не знаю другого способа, который не использует to_string() или циклы для отдельных битов.

...