Битовые операции (поменять местами два соседних бита в числе)
Язык: Си. Нужны корректировки к коду и помощь с ним. Цель: написание программы, которая будет получать с клавиатуры целое число и возвращать другое число, где переставлены местами соседние биты (0 и 1, 2 и 3, 4 и 5 и т.д). Например:
Введено: 163 = 0хА3 = 10100011 Результат: 83 = 0х53 = 01010011
- Вводится «новый» тип данных:
typedef unsigned int integer_tp;
//typedef unsigned short integer_tp;
//typedef unsigned char integet_tp;
//typedef unsigned long integer_tp;
- Результат: числа в десятичной, шестнадцатеричной и двоичной СС (и входное, и результат)
Проблемы:
- Не понимаю, как можно изменить код, чтобы сам обмен битов производился без «вспомогательного» массива. Я понимаю, что решение этой зэчасти задачи в целом странное, поэтому и хотелось бы попросить предложить иное. Спасибо!
- Где и как именно корректно использовать еще один тип тип maxint, чтобы он решал следующую проблему: все эти типы данных имеют разный размер, из-за чего тоже возникают сложности, поскольку число нужно считывать с клавиатуры. Если использовать один и тот же флаг, то будут и переполнения, и, наоборот, может быть недостаточно данных. Размер maxint соответствует максимальному из предложенных выше типов данных для integer_tp. Не пишите, пожалуйста, о том, что в коде ниже путаница со считыванием и выводом типов данных, я вижу это, но не знаю, как изменить.
Код:
#pragma warning(disable: 4996)
#include <stdio.h>
#include <locale.h>
#include <limits.h>
typedef unsigned int integer_tp;
// typedef unsigned short integer_tp;
// typedef unsigned char integet_tp;
// typedef unsigned long integer_tp;
typedef unsigned long maxint;
integer_t process(integer_tp b) {
int f, i;
unsigned int m[4] = { 0,2,1,3 };
for (i = 0; i < 8*sizeof(integer_tp); i += 2) {
f = (b >> i) & 3;
b = (b & (~(3 << i))) | (m[f] << i);
}
printf("%d", b);
}
void tobin(integer_tp g) {
if (g == 0) {
printf("\n");
return;
}
printf("%ld", g & 1);
tobin(g >> 1);
}
int main() {
maxint m;
printf("Введите число: ");
scanf("%lu", &m);
process(m);
return 0;
}
Ответы (2 шт):
Автор решения: Harry
→ Ссылка
Вам надо два конкретных бита?
Вот обмен i-го и j-го битов в переменной b:
unsigned int swap(unsigned int b, unsigned int i, unsigned int j)
{
if (i > j) { unsigned int t = i; i = j; j = t; }
unsigned int maski = 1u << i;
unsigned int maskj = 1u << j;
return ((b&maski) << (j-i)) | ((b&maskj) >> (j-i)) | (b&~(maski|maskj));
}
Или задача обменять все пары битов? Для всех пар это делается еще проще:
unsigned int pair_swap(unsigned int b)
{
return ((b&0x55555555) << 1) | ((b&0xAAAAAAAA) >> 1);
}
Даже распишу :)
b abcdefghijklmnopqrstuvwxyzABCDEF
0x55555555 01010101010101010101010101010101
b & 0x55555555 0b0d0f0h0j0l0n0p0r0t0v0x0z0B0C0F
b&0x55555555 << 1 b0d0f0h0j0l0n0p0r0t0v0x0z0B0C0F0
0xAAAAAAAA 10101010101010101010101010101010
b & 0xAAAAAAAA a0c0e0g0i0k0m0o0q0s0u0w0y0A0C0E0
b&0xAAAAAAAA >> 1 0a0c0e0g0i0k0m0o0q0s0u0w0y0A0C0E
b&0x55555555<<1 |
b&0xAAAAAAAA>>1 badcfehgjilknmporqtsvuxwzyBADCFE
Автор решения: Виктор
→ Ссылка
Такой вариант:
// Функция для замены 'b' битов,
// начиная с позиции 'p' и 'q', в целом числе 'n'
int swap(int n, int p, int q, int b)
{
int x = ((n >> p) ^ (n >> q));
x = x & ((1 << b) - 1);
return n ^ ((x << p) | (x << q));
}
int main()
{
int n = 0xAA; // исходное число
int p = 0, q = 1; // p - bit №1 q - bit №2
int b = 1; // сколько бит поменять
for(int i=0; i<sizeof(int)*8; i+=2)
{
p=i;
q=i+1;
n = swap (n, p, q, b);
}
// n - новое число
return 0;
}
На входе n = 0xAAAA на выходе 0x5555
0xAAAA = 1010101010101010
0x5555 = 0101010101010101
0x9999 = 1001100110011001
0x6666 = 0110011001100110