Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.05.2012, 15:09   #1
Вечный_студент
Пользователь
 
Аватар для Вечный_студент
 
Регистрация: 11.11.2011
Сообщений: 45
По умолчанию замена битов в числе

Код:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

main()
{
	int a,i,b;
	srand(time(NULL));

	a=2147483640;
	printf("a = %d\n",a);
	for (i=31; i>=0; i--)
		printf("%d",(a>>i)&1);

	i=0; 
	printf("\n");
	while (i<32)&(((b<<i)|0x7)==0))
	{
		if ((a&7)==0)
		{
                      b|=(6<<i);
                      i+=4; 
                      a>>=3;
                }
		else
		{
                       b|=((a&1)<<i);
                       a>>=1;
                       ++i;
                 }

	}
	printf("\nresult=%d\n",b);
	for (i=31; i>=0;i--)
		printf("%d",((b>>i)&1));
	printf("\n\n");
	return 0;
}
Всем доброго дня!
Вот небольшая программа. Она должна находить в числе последовательность бит '000' и заменять на '0110'.

подскажите в чем ошибка?
Крепкая стена строится из маленьких кирпичей.
Но если положил первый кирпич криво, как ни старайся, стена кривой будет.
Вечный_студент вне форума Ответить с цитированием
Старый 07.05.2012, 15:44   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Наверное, стоит получше сформулировать условие. А то можно подумать, что при наличии 32 бит в числе хотите получить 33?
И если подобная вставка (замена) сама сформирует новую последовательность из трех нулевых битов, то каковы условия обработки этой ситуации?
А сейчас вообще вижу даже не компилируемую программу из-за пропущенной открывающей скобки, и нет инициализации переменной b (че она ваще делает)?
И не понятно условие выполнения цикла.

PS. может, чтоб не путаться, разбить число на триады бит, и оперировать ими:
Код:
struct TRIOBIT 
{
	unsigned t0 :3;
	unsigned t1 :3;
	unsigned t2 :3;
	unsigned t3 :3;
	unsigned t4 :3;
	unsigned t5 :3;
	unsigned t6 :3;	
	unsigned t7 :3;
	unsigned t8 :3;
	unsigned t9 :3;
	unsigned t10 :2; // старшие биты (остаток)
};


union UNI
{
	int i32;
	TRIOBIT tb;
};

main()
{

	int z = 12345;
	UNI u = {z};
}

Последний раз редактировалось EUGY; 07.05.2012 в 16:03.
EUGY вне форума Ответить с цитированием
Старый 07.05.2012, 18:06   #3
Вечный_студент
Пользователь
 
Аватар для Вечный_студент
 
Регистрация: 11.11.2011
Сообщений: 45
По умолчанию

оу шит)

действительно пропустил скобку.
Нет разбивать на триады не проще.

Суть в том, что программа должна заменять последовательность '000' до тех пор, пока это последовательность есть в числе. (у меня именно это не получается)

вот рабочий код.

Код:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

main()
{
	int a,i,b;
	srand(time(NULL));

	a=2147483640;
	printf("a = %d\n",a);
	for (i=31; i>=0; i--)
		printf("%d",(a>>i)&1);

	i=0; 
	printf("\n");
        b=0;
	while (i<32)
	{
		if ((a&7)==0)
		{
                      b|=(6<<i);
                      i+=4; 
                      a>>=3;
                }
		else
		{
                       b|=((a&1)<<i);
                       a>>=1;
                       ++i;
                 }

	}
	printf("\nresult=%d\n",b);
	for (i=31; i>=0;i--)
		printf("%d",((b>>i)&1));
	printf("\n\n");
	return 0;
}
и да. b инициализирована
Крепкая стена строится из маленьких кирпичей.
Но если положил первый кирпич криво, как ни старайся, стена кривой будет.

Последний раз редактировалось Вечный_студент; 07.05.2012 в 18:12.
Вечный_студент вне форума Ответить с цитированием
Старый 07.05.2012, 20:07   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Ребус вообщем не плохой
Решал в лоб, поэтому может не оптимально и мог какие-то нюансы упустить:
Код:
void printbits(int p)
{
	for (int i = 32; i--;)
		printf("%d", (p >> i) & 1);
	printf ("\n");
}


int func(int p)
{

	for (int i = 2; i < 32 ; i++) // int i = 2, начало чтения - третий бит
	{
			// бит сегодня
			int q2 = (p >> i) & 1;
			// вчера
			int q1 = (p >> (i - 1)) & 1;
			// позавчера
			int q0 = (p >> (i - 2)) & 1;

			// если триада нулевая, сдвинуть еще непрочитанные биты
			//  на один порядок, а бит сегодня-вчера установить в 1
			if (!(q2||q1||q0))
			{
				// запоминаем прочитанное состояние, то есть кладем маску из единиц
				int sav = p & ( (1<<i) - 1);
				// вычитаем, оставляя только непрочитанные биты
				p = p - sav; 
				// сдвигаем на порядок
				p = p << 1;
				// вносим прочитанное обратно
				p =  p + sav;
				// два бита в единицу
				p |= 1 << i;
				p |= 1 << (i-1);
			}

	}

	return p;
}

main()
{
	int a=2147483640;

	//---
	printf("a = %d\n", a);
	printbits (a);
	//---
	int b = func(a);
	//---
	printf("b = %d\n", b);
	printbits (b);

	return 0;
}
EUGY вне форума Ответить с цитированием
Старый 08.05.2012, 11:39   #5
Вечный_студент
Пользователь
 
Аватар для Вечный_студент
 
Регистрация: 11.11.2011
Сообщений: 45
По умолчанию

на удивление работает Но вызов функций очень ресурсоемкая операция.
Поэтому, я всё же больше склоняюсь к своему коду. Он и проще и оптимальнее.
Не подскажете, как мне его преобразовать, чтобы программа после себя не оставляла последовательности 000?

на примере числа 2147483616
двоичная форма числа: 11111111111111111111111111100000
в ответ программа выдает: 11111111111111111111111111000110
Крепкая стена строится из маленьких кирпичей.
Но если положил первый кирпич криво, как ни старайся, стена кривой будет.
Вечный_студент вне форума Ответить с цитированием
Старый 08.05.2012, 15:33   #6
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Вот первая оптимизация моего способа:
Код:
int func(int p)
{
	for (int i = 2; i < 32 ; i++) 
	{
		if (!(p & (((1<<i+1) - 1)- ((1<<i-2) - 1))))
		{
				int sav = p & ((1<<i) - 1);
				p = sav + ((p - sav) << 1); 
				p |= 1 << i | 1 << (i-1);
		}
	}
	return p;
}
Что исправлять в Вашем - не знаю.
PS. может стоит обратиться в ветку ассемблера?

Последний раз редактировалось EUGY; 08.05.2012 в 15:36.
EUGY вне форума Ответить с цитированием
Старый 09.05.2012, 03:21   #7
Вечный_студент
Пользователь
 
Аватар для Вечный_студент
 
Регистрация: 11.11.2011
Сообщений: 45
По умолчанию

Код:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

main()
{
	int a,i;
	srand(time(NULL));

	a=rand()%2147483616;
	printf("a = %d\n",a);
	for (i=31; i>=0; i--)
		printf("%d",(a>>i)&1);
 
	printf("\n");

	for (i = 2; i < 32 ; i++) 
	{
		if (!(a & (((1<<i+1) - 1)- ((1<<i-2) - 1))))
		{
				int sav = a & ((1<<i) - 1);
				a = sav + ((a - sav) << 1); 
				a |= 1 << i | 1 << (i-1);
		}
	}

	printf("\nresult=%d\n",a);
	for (i=31; i>=0;i--)
		printf("%d",((a>>i)&1));
	printf("\n\n");
	return 0;
}
вот работает, а говорите не знаете. Спасибо вам.
полностью правильно работающий код
Крепкая стена строится из маленьких кирпичей.
Но если положил первый кирпич криво, как ни старайся, стена кривой будет.
Вечный_студент вне форума Ответить с цитированием
Старый 09.05.2012, 14:47   #8
Вечный_студент
Пользователь
 
Аватар для Вечный_студент
 
Регистрация: 11.11.2011
Сообщений: 45
По умолчанию

Код:
if (!(a&(((1<<i+1)-1)-((1<<i-2)-1))))

объясните только вот эту строчку. плохо понимаю что и при каких условиях здесь происходит.

на выходе получается либо 1 либо 0 и, в зависимости от этого, выполняется if?
Крепкая стена строится из маленьких кирпичей.
Но если положил первый кирпич криво, как ни старайся, стена кривой будет.
Вечный_студент вне форума Ответить с цитированием
Старый 09.05.2012, 16:45   #9
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
на выходе получается либо 1 либо 0 и, в зависимости от этого, выполняется if?
Да.

Код:
(((1<<i+1)-1)-((1<<i-2)-1)) // это число из трех смежных единичных бит.
В зависимости от итерации i ее изменения такие
Цитата:
.....000000111
.....000001110
.....000011100
.....000111000
.............. итд
И это число является маской проверки для второго операнда.
Если у него эти биты не установлены, выполняется условие if
EUGY вне форума Ответить с цитированием
Старый 09.05.2012, 17:04   #10
Вечный_студент
Пользователь
 
Аватар для Вечный_студент
 
Регистрация: 11.11.2011
Сообщений: 45
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Да.

Код:
(((1<<i+1)-1)-((1<<i-2)-1)) // это число из трех смежных единичных бит.
а можно расписать подробно, как путем этих не хитрых операций получается число 111 (7)?
Крепкая стена строится из маленьких кирпичей.
Но если положил первый кирпич криво, как ни старайся, стена кривой будет.

Последний раз редактировалось Вечный_студент; 09.05.2012 в 17:07.
Вечный_студент вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
замена битов в числе Вечный_студент Помощь студентам 11 08.05.2012 00:21
Сдвиг битов XOKS Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 5 08.11.2010 18:11
Перемешивание позиций битов в числе explored Общие вопросы C/C++ 6 27.10.2010 23:14
Замена второго бита в числе SZR Помощь студентам 4 25.01.2008 20:16
Перестановка битов. RegentM Общие вопросы Delphi 3 05.11.2007 17:23