Я хочу извлечь биты десятичного числа.
Например, 7 - это двоичный 0111, и я хочу получить 0 1 1 1 все биты, хранящиеся в bool. Как я могу это сделать?
Хорошо, цикл - не лучший вариант, могу я сделать что-нибудь еще для этого?
Ответы:
Если вам нужен k-й бит числа n, выполните
(n & ( 1 << k )) >> k
Здесь мы создаем маску, применяем маску к n, а затем сдвигаем вправо значение маски, чтобы получить именно тот бит, который нам нужен. Мы могли бы описать это более полно как:
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
Вы можете узнать больше о битовой маскировке здесь .
Вот программа:
#include <stdio.h>
#include <stdlib.h>
int *get_bits(int n, int bitswanted){
int *bits = malloc(sizeof(int) * bitswanted);
int k;
for(k=0; k<bitswanted; k++){
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
bits[k] = thebit;
}
return bits;
}
int main(){
int n=7;
int bitswanted = 5;
int *bits = get_bits(n, bitswanted);
printf("%d = ", n);
int i;
for(i=bitswanted-1; i>=0;i--){
printf("%d ", bits[i]);
}
printf("\n");
}
structможет быть полезным, поскольку вы получаете все необходимые данные за одну операцию.
По просьбе, я решил расширить свой комментарий к ответу указательного пальца до полноценного ответа. Хотя его ответ правильный, он излишне сложен. Кроме того, все текущие ответы используют подписанные ints для представления значений. Это опасно, поскольку сдвиг вправо отрицательных значений определяется реализацией (т.е. не переносится), а сдвиг влево может привести к неопределенному поведению (см. Этот вопрос ).
Путем сдвига желаемого бита вправо в позицию младшего разряда можно выполнить маскирование с помощью 1. Нет необходимости вычислять новое значение маски для каждого бита.
(n >> k) & 1
Как законченная программа, вычисляющая (и впоследствии распечатывающая) массив однобитовых значений:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
unsigned
input = 0b0111u,
n_bits = 4u,
*bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
bit = 0;
for(bit = 0; bit < n_bits; ++bit)
bits[bit] = (input >> bit) & 1;
for(bit = n_bits; bit--;)
printf("%u", bits[bit]);
printf("\n");
free(bits);
}
Предполагая, что вы хотите вычислить все биты, как в этом случае, а не конкретный, цикл можно изменить на
for(bit = 0; bit < n_bits; ++bit, input >>= 1)
bits[bit] = input & 1;
Это модифицируется inputна месте и, таким образом, позволяет использовать однобитовый сдвиг постоянной ширины, который может быть более эффективным на некоторых архитектурах.
Вот один способ сделать это - есть много других:
bool b[4];
int v = 7; // number to dissect
for (int j = 0; j < 4; ++j)
b [j] = 0 != (v & (1 << j));
Трудно понять, почему использование цикла нежелательно, но развернуть цикл достаточно просто:
bool b[4];
int v = 7; // number to dissect
b [0] = 0 != (v & (1 << 0));
b [1] = 0 != (v & (1 << 1));
b [2] = 0 != (v & (1 << 2));
b [3] = 0 != (v & (1 << 3));
Или вычисление константных выражений в последних четырех операторах:
b [0] = 0 != (v & 1);
b [1] = 0 != (v & 2);
b [2] = 0 != (v & 4);
b [3] = 0 != (v & 8);
@prateek спасибо за вашу помощь. Я переписал функцию с комментариями для использования в программе. Увеличьте 8 для большего количества бит (до 32 для целого числа).
std::vector <bool> bits_from_int (int integer) // discern which bits of PLC codes are true
{
std::vector <bool> bool_bits;
// continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
for (int i = 0; i < 8; i++)
{
bool_bits.push_back (integer%2); // remainder of dividing by 2
integer /= 2; // integer equals itself divided by 2
}
return bool_bits;
}
Если вам не нужны циклы, вам придется их записать:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num = 7;
#if 0
bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
#else
#define BTB(v,i) ((v) & (1u << (i))) ? true : false
bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
#undef BTB
#endif
printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);
return 0;
}
Как показано здесь, это также работает в инициализаторе.
С помощью std::bitset
int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
(n >> k) & 1одинаково действителен и не требует вычисления маски, поскольку маска постоянна из-за сдвига перед маскированием, а не наоборот.