11.19. Выполнение операций с битовыми наборами
11.19. Выполнение операций с битовыми наборами
Проблема
Требуется реализовать основные арифметические операции и операции сравнения для набора бит, рассматривая его как двоичное представление целого числа без знака.
Решение
Программный код примера 11.36 содержит функции, которые позволяют выполнять арифметические операции и операции сравнения с шаблоном класса bitset из заголовочного файла <bitset>, рассматривая его как целый тип без знака.
Пример 11.36. bitset_arithmetic.hpp
#include <stdexcept>
#include <bitset>
bool fullAdder(bool b1, bool b2, bool& carry) {
bool sum = (b1 ^ b2) ^ carry;
carry = (b1 && b2) || (b1 && carry) || (b2 && carry);
return sum;
}
bool fullSubtractor(bool b1, bool b2, bool& borrow) {
bool diff;
if (borrow) {
diff = !(b1 ^ b2);
borrow = !b1 || (b1 && b2);
} else {
diff = b1 ^ b2;
borrow = !b1 && b2;
}
return diff;
}
template<unsigned int N>
bool bitsetLtEq(const std::bitset<N>& x, const std::bitset<N>& y) {
for (int i=N-1; i >= 0; i--) {
if (x[i] && !y[i]) return false;
if (!x[i] && y[i]) return true;
}
return true;
}
template<unsigned int N>
bool bitsetLt(const std::bitset<N>& x, const std::bitset<N>& y) {
for (int i=N-1; i >= 0, i--) {
if (x[i] && !y[i]) return false;
if (!x[i] && y[i]) return true;
}
return false;
}
template<unsigned int N>
bool bitsetGtEq(const std::bitset<N>& x, const std::bitset<N>& y) {
for (int i=N-1; i >= 0; i--) {
if (x[i] && !y[i]) return true;
if (!x[i] && y[i]) return false;
}
return true;
}
template<unsigned int N>
bool bitsetGt(const std::bitset<N>& x, const std::bitset<N>& y) {
for (int i=N-1; i >= 0; i--) {
if (x[i] && !y[i]) return true;
if (!x[i] && y[i]) return false;
}
return false;
}
template<unsigned int N>
void bitsetAdd(std::bitset<N>& x, const std::bitset<N>& y) {
bool carry = false;
for (int i = 0; i < N; i++) {
x[i] = fullAdder(x[i], y[x], carry);
}
}
template<unsigned int N>
void bitsetSubtract(std::bitset<N>& x, const std::bitset<N>& y) {
bool borrow = false;
for (int i = 0; i < N; i++) {
if (borrow) {
if (x[i]) {
x[i] = y[i];
borrow = y[i];
} else {
x[i] = !y[i];
borrow = true;
}
} else {
if (x[i]) {
x[i] = !y[i];
borrow = false;
} else {
x[i] = y[i];
borrow = y[i];
}
}
}
}
template<unsigned int N>
void bitsetMultiply(std::bitset<N>& x, const std::bitset<N>& y) {
std::bitset<N> tmp = x;
x.reset();
// мы хотим минимизировать количество операций сдвига и сложения
if (tmp.count() < y.count()) {
for (int i=0; i < N; i++) if (tmp[i]) bitsetAdd(x, у << i);
} else {
for (int i=0; i < N; i++) if (y[i]) bitsetAdd(x, tmp << i);
}
}
template<unsigned int N>
void bitsetDivide(std::bitset<N> x, std::bitset<N> y,
std::bitset<N>& q, std::bitset<N>& r) {
if (y.none()) {
throw std::domain_error("division by zero undefined");
}
q.reset();
r.reset();
if (x.none()) {
return;
}
if (x == y) {
q[0] = 1;
return;
}
r = x;
if (bitsetLt(x, y)) {
return;
}
// подсчитать количество значащих цифр в делителе и делимом
unsigned int sig_x;
for (int i=N-1; i>=0; i--) {
sig_x = i;
if (x[i]) break;
}
unsigned int sig_y;
for (int i=N-1; i>=0; i--) {
sig_y = i;
if (y[i]) break;
}
// выровнять делитель по отношению к делимому
unsigned int n = (sig_x — sig_y);
y <<= n;
// обеспечить правильное число шагов цикла
n += 1;
// удлиненный алгоритм деления со сдвигом и вычитанием
while (n--) {
// сдвинуть частное влево
if (bitsetLtEq(y, r)) {
// добавить новую цифру к частному
q[n] = true;
bitset.Subtract(r, y);
}
// сдвинуть делитель вправо
y >>= 1;
}
}
Пример 11.37 показывает, как можно использовать заголовочный файл bitset_arithmetic.hpp.
Пример 11.37. Применение функций bitset_arithmetic.hpp
#include "bitset_arithmetic.hpp"
#include <bitset>
#include <iostream>
#include <string>
using namespace std;
int main() {
bitset<10> bits1(string("100010001"));
bitset<10> bits2(string("000000011"));
bitsetAdd(bits1, bits2);
cout << bits1.to_string<char, char_traits<char>, allocator<char> >() << endl;
}
Программа примера 11.37 выдает следующий результат.
0100010100
Обсуждение
Шаблон класса bitset содержит основные операции по манипулированию битовыми наборами, но не обеспечивает арифметические операции и операции сравнения. Это объясняется тем, что в библиотеке нельзя заранее точно предвидеть, какой числовой тип будет использоваться для представления произвольного битового набора согласно ожиданиям программиста.
В функциях примера 11.36 считается, что bitset представляет собой целый тип без знака, и здесь обеспечиваются операции сложения, вычитания, умножения, деления и сравнения. Эти функции могут составить основу для представления специализированных целочисленных типов, и именно для этого они используются в рецепте 11.20.
В примере 11.36 я использовал не самые эффективные алгоритмы. Я применил самые простые алгоритмы, потому что их легче понять. В существенно более эффективной реализации использовались бы аналогичные алгоритмы, которые работали бы со словами, а не с отдельными битами.
Смотри также
Рецепт 11.20.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Функции XPath для работы с наборами узлов
Функции XPath для работы с наборами узлов Следующие функции XPath работают с наборами узлов:• count(node-set). Возвращает число узлов в наборе узлов;• id(string ID). Возвращает набор узлов элемента, ID которого совпадает с переданной функции строкой, или пустой набор узлов, если таковых
Выполнение основных операций с файловой системой
Выполнение основных операций с файловой системой Для работы с файловой системой из сценариев WSH предназначены восемь объектов, главным из которых является FileSystemObject. С помощью методов объекта FileSystemObject можно выполнять следующие основные действия:? копировать или
if - Выполнение или не выполнение предложений в зависимости от условий
if - Выполнение или не выполнение предложений в зависимости от условий ifПозволяет выполнить или не выполняет определенные предложения в зависимости от заданного условияСинтаксис:if (condition) { statements}Аргументы:В целом, предложение if завершается закрывающей фигурной скобкой
Контроль операций NTP
Контроль операций NTP Помимо визуального контроля показаний часов с помощью программы xclock, для мониторинга операций NTP часто применяется программа ntpq. После вызова эта программа запрашивает команды, определяющие ее дальнейшую работу. Команды вводятся в текстовом режиме.
26.6.2. Выполнение операций над семафорами
26.6.2. Выполнение операций над семафорами Для выполнения операций над множеством семафоров служит системный вызов semop():int semop(int semid, struct sembuf *sops, unsigned nsops);Первый аргумент — это идентификатор семафора, возвращаемый вызовом semget(). Второй — это массив операций, которые нужно
36. Перегрузка операций
36. Перегрузка операций Часто программы имеют дело с объектами, которые являются представлениями абстрактных понятий. К примеру, тип данных int в C++ вместе с операциями +, —, *, / и т. д. является реализацией математического понятия целых чисел. Подобные понятия чаще всего
Управление наборами данных с помощью объектов Collection
Управление наборами данных с помощью объектов Collection Если нужно работать с наборами элементов информации, создайте для этой информации объект Collection (Коллекция). Как уже говорилось в главе 12, в VBA родовой класс Collection предназначен для хранения практически всего, что только
12.4.2. Совмещение операций
12.4.2. Совмещение операций В главе 5 сравнивались протоколы РОРЗ и IMAP для опроса удаленных почтовых серверов. При этом было отмечено, что IMAP-запросы (в отличие от РОРЗ-запросов) маркируются идентификатором запроса, сгенерированным клиентом. Сервер, отправляя обратно ответ,
7.8. Выполнение для последовательностей операций над множествами
7.8. Выполнение для последовательностей операций над множествами ПроблемаИмеются последовательности, которые требуется реорганизовать с помощью операций над множествами, таких как объединение (union), различие (difference) или пересечение (intersection).РешениеДля этой цели
Перегрузка операций
Перегрузка операций В C#, как и в любом другом языке программирования, есть свой ограниченный набор лексем, используемых для выполнения базовых операций со встроенными типами. Так, вы знаете, что операция + применима к двум целым числам и в результате дает их сумму.//
Старшинство операций
Старшинство операций В соответствии с принятым в языке Си порядком вычислений операции увеличения и уменьшения имеют очень высокий уровень старшинства; только круглые скобки обладают более высоким приоритетом. Поэтому выражение x*y++ означает (x)*(y++), а не (x*y)++, что
7.11. Синхронное выполнение задач с помощью операций
7.11. Синхронное выполнение задач с помощью операций Постановка задачи Необходимо синхронно выполнить серию
7.12. Асинхронное выполнение задач с помощью операций
7.12. Асинхронное выполнение задач с помощью операций Постановка задачи Требуется параллельно выполнять
Урок 9. Выполнение операций
Урок 9. Выполнение операций Вам наверняка понадобится изменять данные, хранящиеся в переменной. Мы уже рассматривали, как с помощью команд ++ или += изменять значение переменной. В вашем распоряжении также имеется большой набор других операций.Давайте начнем с переменных,
Использование операций
Использование операций Представления стека при всех их различиях объединяет то, что они описывают структуру "хранения" (т.е. структуру, используемую для хранения других объектов), к которой применяются определенные операции, обладающие определенными свойствами.