Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.80/15: Рейтинг темы: голосов - 15, средняя оценка - 4.80
ivani493
1

Побитовые операции (программа, которая интерпретирует старшие 3 бита как некоторое число n...)

23.01.2013, 14:05. Показов 3063. Ответов 23
Метки нет (Все метки)

Уважаемые форумчане, нужна ваша помощь.
Нужно составить программу, которая интерпретирует старшие 3 бита как некоторое число n и оставшиеся разряды сдвинуть циклически влево на n разрядов.
За помощь буду очень благодарен!

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.01.2013, 14:05
Ответы с готовыми решениями:

Как обнулить первые 4-е бита начиная с певого заряженного (первые - старшие биты)
Собственно, вопрос в заголовке.

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

Дано 16-и битное слово, нужно записать старшие 3 бита в обратном порядке
Мальчики, всем привет! На этой неделе нужно сдавать лабораторную, преподаватель назвал эту...

Побитовые операции: проверить, является ли число степенью двойки
Всем добрый день, только начал изучать Java и застрял на одной задаче по побитовым операциям, вот...

23
18 / 18 / 4
Регистрация: 18.05.2010
Сообщений: 83
23.01.2013, 14:27 2
Цитата Сообщение от ivani493 Посмотреть сообщение
и оставшиеся разряды сдвинуть циклически влево на n разрядов.
сдвинуть только их? 3 старших не трогать?
0
ivani493
23.01.2013, 18:46 3
Да
4 / 4 / 4
Регистрация: 14.09.2012
Сообщений: 64
25.01.2013, 21:22 4
интерпретирует старшие 3 бита как некоторое число n и оставшиеся разряды сдвинуть циклически влево на n разрядов.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
int x=1234;
namespace q{int x1=x;};
int main()
{
int t=1073741824;
int i=0;
while(t>x){
t=t>>1;
i++;}
int t1=(31-i);
x=x>>(t1-3);
q::x1=q::x1>>x;
std::cout<<q::x1<<'\n';
std::cin.get();
std::cin.get();
 
    return 0;
}
Подскажите пожалуйста насколько плохо решено или решено ли вообще.
0
3414 / 2773 / 751
Регистрация: 25.03.2012
Сообщений: 10,085
Записей в блоге: 1
25.01.2013, 22:40 5
зачем выпендриваться с неймспейсами?
я нифига не понял. Где взято 3 бита то? Я предлагаю их брать как
C++
1
2
int low3bits=x&7;//младшие 3 бита
int high3bits=x&0xE0;//старшие 3 бита
А над твоим кодом я чуток подумал и всё равно нифига не понял

Добавлено через 5 минут
а ... там не в байте, а в инте биты!
1
4 / 4 / 4
Регистрация: 14.09.2012
Сообщений: 64
26.01.2013, 00:42 6
Взял максимальное положение 1 без учета знакового бита, это t.

C++
1
2
3
while(t>x){
t=t>>1;
i++;}
Cделал проход для совпадения старшего бита рассматриваемого числа с t, для этого потребовалось i сдвигов.
C++
1
int t1=(31-i);
Вычисления номера старшего бита.
C++
1
x=x>>(t1-3);
Сдвиг для того, что-бы остались 3 искомых бита.Фактически 3х битное число.
C++
1
q::x1=q::x1>>x;
Это сдвиг разрабатываемого, числа на 3х битное число оставшее в результате предыдущего преобразования.

Добавлено через 1 час 17 минут
C++
1
2
int low3bits=x&7;//младшие 3 бита
int high3bits=x&0xE0;//старшие 3 бита
Я не знал, что так можно извлекать биты, спасибо за информацию.

Добавлено через 31 минуту
Но как оно функционирует? Чему он возвращает high?
x&7
0
419 / 418 / 167
Регистрация: 28.11.2010
Сообщений: 1,183
26.01.2013, 03:36 7
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
int main()
{
    unsigned int a=0xafffffff;
    unsigned int mask=0xe0000000;
    unsigned int len=8*sizeof(int);
    unsigned int chislo=(a & mask)>>(len-3);
    unsigned int shifted=a;
    for (unsigned int i=0; i<len; ++i) /*rol shift*/
        (shifted & 0x10000000) ? (shifted <<= 1)|=1:(shifted <<= 1)|=0;
    cout <<hex<<chislo<<endl;
    cout <<hex<<shifted<<endl;
    return 0;
}
Добавлено через 21 минуту

Добавлено через 17 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
    unsigned int a=0xafaff4f5; //число
    unsigned int mask=0xe0000000; // старшие три разряда
    unsigned int mask1=0x10000000; // 28 разряд
    //unsigned int mask2=0x1fffffff; // старшие три разряда
    const unsigned int len=32;//8*sizeof(int);
    const unsigned int n=3;
    unsigned int chislo=(a & mask)>>(len-n); //получаем старшие 3 разряда
    unsigned int shifted=a;
    for (unsigned int i=0; i<len-n; ++i) { /*rol shift*/
        // if (i==0) (shifted & mask1) ? shifted|=mask1 : shifted&=mask2; // записываем в 29-31 значение 28 разряда 
        (shifted & mask1) ? (shifted <<= 1)|=1:(shifted <<= 1)|=0; // циклический сдвиг через 28 разряд
        cout <<bitset<len>(shifted)<<endl;
    }
    shifted=(shifted & ~mask)|(a & mask); // восстанавливаем 31-29 разряды
    cout<<"======================="<<endl;
    cout <<bitset<len>(a)<<endl;
    cout <<bitset<len>(mask)<<endl;
    cout <<bitset<len>(a & mask)<<endl;
    cout <<bitset<len>(mask1)<<endl;
    cout <<bitset<n>(chislo)<<endl;
    cout <<bitset<len>(shifted)<<endl;
    return 0;
}
0
4 / 4 / 4
Регистрация: 14.09.2012
Сообщений: 64
26.01.2013, 18:20 8
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
unsigned int x=1234;
unsigned int x1=1234;
int main()
{
unsigned int t=2147483648;
unsigned int i=0;
while(t>=x){
t=t>>1;
i++;}//отсуп от 32 бита
unsigned int t1=(32-i);//количество бит
x=x>>(t1-3);//значение 3х бит
x1=x1<<(32-t1+3);//удаляем первые 3 бита
x1=x1>>(32-t1+3);//восстанавливаем без 3х бит
x1=x1>>x;//сдвигаем на число полученное из 1х 3х бит 14 и 15 можно объеденить.
std::cout<<x1<<'\n';
В предыдущем случае учитывал первые 3 бита, сейчас откорректировал.
0
419 / 418 / 167
Регистрация: 28.11.2010
Сообщений: 1,183
26.01.2013, 19:18 9
Valli1, сдвинуть циклически
0
4 / 4 / 4
Регистрация: 14.09.2012
Сообщений: 64
26.01.2013, 19:33 10
Цитата Сообщение от vua72 Посмотреть сообщение
Valli1, сдвинуть циклически
А, что мое не правильно? А, блин вы про условие.Бегло быстро его прочитал ,особо не вдумываясь, точно, спасибо.

Добавлено через 8 минут
Хотя какая разница, сдвигать на один бит 13 и 14 строки????
0
419 / 418 / 167
Регистрация: 28.11.2010
Сообщений: 1,183
26.01.2013, 19:42 11
циклически, это ссылка. в данном случае через 28 разряд
hxxp://ru.wikipedia.org/wiki/Битовый_сдвиг
0
4 / 4 / 4
Регистрация: 14.09.2012
Сообщений: 64
26.01.2013, 21:30 12
Цитата Сообщение от vua72 Посмотреть сообщение
циклически, это ссылка. в данном случае через 28 разряд
hxxp://ru.wikipedia.org/wiki/Битовый_сдвиг
C++
1
2
3
4
x=x>>(t1-3);//значение 3х бит
x1=x1<<(32-t1+3);//удаляем первые 3 бита
x1=x1>>(32-t1+3);//восстанавливаем без 3х бит
x1=x1>>x;
Имел ввиду, что любой из этих сдвигов можно представить в виде цикла for и пр., тут за один шаг, а можно кол-во шагов увеличить и все.
0
Модератор
Эксперт по электронике
8494 / 6320 / 855
Регистрация: 14.02.2011
Сообщений: 21,909
26.01.2013, 22:01 13
Цитата Сообщение от ivani493 Посмотреть сообщение
Нужно составить программу, которая интерпретирует старшие 3 бита как некоторое число n и оставшиеся разряды сдвинуть циклически влево на n разрядов.
старшие три бита ЧЕГО?
char?
short?
int?
long?
вот решение для char(8 бит) m число с которым нужно поработать
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
unsigned char ROL(unsigned char val,unsigned char ofset)//функция циклического сдвига влево
{
unsigned char ofsetTmp=ofset%5;// ограничиваем сдвиг он должен быть меньше 5 байт 
unsigned char val1=(val<<ofsetTmp)|(ofsetTmp>>5-ofsetTmp); //циклический сдвиг влево 
return val1&0x1F;// выделяем 5 младших бит  и возвращаем значение
}
 
void fnc()
{
unsigned char tmp=m&0xE0; // выделяем три старших байта 
unsigned char res=tmp>>5; // делаем из них число 
unsigned char mL=m&0x1F; // выделяем 5 младших бит 
unsigned char resROL=ROL(mL,res);//сдвигаем их
unsigned char res1=resROL|tmp;  // совмешаем число 
}
Добавлено через 2 минуты
Цитата Сообщение от Valli1 Посмотреть сообщение
Имел ввиду, что любой из этих сдвигов можно представить в виде цикла for и пр.,
все циклические сдвиги делаются тремя операциями(4 если разрядность не равна базовым)
два сдвига и один ИЛИ ( и И если разрядность не равна базовым)
0
4 / 4 / 4
Регистрация: 14.09.2012
Сообщений: 64
26.01.2013, 22:43 14
циклические сдвиги
Я недавно узнал о простом сдвиге. И думал, что сдвинуть циклически, это использовать цикл для изменения
значения (
C++
1
a>>b
) b, а не использовать ранее мне неизвестный "циклический сдвиг".
P.S. "Я же только учусь."
0
Модератор
Эксперт по электронике
8494 / 6320 / 855
Регистрация: 14.02.2011
Сообщений: 21,909
26.01.2013, 23:34 15
Цитата Сообщение от Valli1 Посмотреть сообщение
Я недавно узнал о простом сдвиге. И думал, что сдвинуть циклически,
нет
это то что выходит с одной стороны приходит в другую
допустим нужно сдвинуть байт (8 бит) влево циклически
в нем число
01100011
11000110 первый сдвиг пока не отличается от простого сдвига
10001101 второй единица перешла из старшего разряда в младший
00011011 третий единица перешла из старшего разряда в младший
00110110 четвертый ноль перешел из старшего разряда в младший
01101100 пятый
11011000 шестой
10110001 седьмой
01100011 восьмой получили первоначальное число
то же самое и со сдвигом вправо только из младшего значение переходит в старший
в отличии от ассемблера в С нет команды циклического сдвига
можно конечно тупо сделать это циклом проверяя младший(старший) бит

C++
1
2
3
4
5
6
7
8
9
for(int i=0;i<n;i++)
{
   if(r&0x80)
     m=0x01;
   else
     m=0;
    r=r<<1; 
    r=r|m;
}
но это долго
есть способ проще
смотри
01100011 надо сдвинуть на три влево
должно получится
00011011
видишь выделенные разряды ушли вправо
делаем так
пишу по шагам
сдвигаем влево на три разряда
01100011<< 3= 00011000
сдвигаем вправо на разность размера числа( у нас 8 бит) и на число сдвига
01100011>> (8-3)=00000011
и складываем их логически (операция ИЛИ)
00011000 | 00000011= 00011011
всего три операции(четыре если считать вычитание)
1
419 / 418 / 167
Регистрация: 28.11.2010
Сообщений: 1,183
27.01.2013, 00:16 16
Единственное, этот алгоритм корректно работает с беззнаковыми, а тупому циклу все равно-знаковые или беззнаковые. Сразу соглашусь, что сдвиги вообще корректно применять к беззнаковым.
1
Модератор
Эксперт по электронике
8494 / 6320 / 855
Регистрация: 14.02.2011
Сообщений: 21,909
27.01.2013, 00:27 17
Цитата Сообщение от vua72 Посмотреть сообщение
Сразу соглашусь, что сдвиги вообще корректно применять к беззнаковым.
имянно
если простой сдвиг вправо (деление на 2) еще имеет место быть для знаковых
то для циклического результат ересь
да и как можно циклически сдвинуть -2?
циклический сдвиг это чисто битовая примочка

Цитата Сообщение от vua72 Посмотреть сообщение
Единственное, этот алгоритм корректно работает с беззнаковыми,
я как то забыл акцентировать на этом внимание в примере сделал а в объяснении нет

Не по теме:

вспоминаю как я переходил на С для микроконтроллеров
надо было сделать "бегуший огонь" туда-сюда влево нормально бежал а вправо набирался
пришлось делать на ассемблере
не знал я тогда разницы для сдвига вправо между signed и unsigned

0
4 / 4 / 4
Регистрация: 14.09.2012
Сообщений: 64
27.01.2013, 00:50 18
но это долго
есть способ проще
Спасибо за доходчивое разъяснение. Буду внедрять в практику.
0
419 / 418 / 167
Регистрация: 28.11.2010
Сообщений: 1,183
27.01.2013, 02:21 19
а вот и код дизассемблера для сдвига вправо
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
57                  return (val >> n % sz) | (val << (sz - n % sz));
                  fror(unsigned char, unsigned char):
0000000000400956:   movzx edi,dil
000000000040095a:   and esi,0x7
000000000040095d:   movzx edx,sil
0000000000400961:   mov ecx,0x8
0000000000400966:   sub ecx,edx
0000000000400968:   mov eax,edi
000000000040096a:   shl eax,cl
000000000040096c:   mov ecx,esi
000000000040096e:   sar edi,cl
0000000000400970:   or eax,edi
58                }
и виновник вытягивания знака
Assembler
1
sar edi,cl
0
Модератор
Эксперт по электронике
8494 / 6320 / 855
Регистрация: 14.02.2011
Сообщений: 21,909
27.01.2013, 02:32 20
Цитата Сообщение от vua72 Посмотреть сообщение
а вот и код дизассемблера для сдвига вправо
если ты мне
то я давно уже знаю разницу между SHR (для беззнаковых) логический сдвиг
и SAR (для знаковых) арифметический сдвиг
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.01.2013, 02:32

Используя побитовые операции, преобразовать десятичное число в двоичное
printf(&quot;Десятичное значение числа: &quot;); scanf(&quot;%d&quot;, &amp;x); a=0; do { a=a+x&amp;1;...

Побитовые системы: Без операции деления на 2 определить, является ли число четным
Помогите пожалуйста составить программы 1) Пользователь вводит целое число. Без операции деления...

Побитовые операции - Длинное целое число разделить на четыре однобайтовых целых числа
Произвольное длинное целое число разделить на четыре однобайтовых целых числа, каждому из которых...

Побитовые операции: получить целое число, отбросив нечетные биты данного числа k
Дано длинное целое неотрицательное число k. Получить целое число, отбросив нечетные биты данного...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.