Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЗадачникПоТПиРнаЭВМ.doc
Скачиваний:
28
Добавлен:
11.03.2016
Размер:
1 Mб
Скачать

Глава 8. Побитовые операции

Побитовые операции можно применять только к целочисленным операндам типа char, short, int, long. Они действуют на отдельные разряды двоичного представления чисел. В С++ определены следующие побитовые операции [32]:

| – побитовое логическое ИЛИ;

& – побитовое логическое И;

^ – побитовое исключающее ИЛИ;

~ – побитовое логическое отрицание;

<< – сдвиг влево;

>> – сдвиг вправо.

Результаты действия побитовых операций на операнды a и b представлены в табл. 8.1.

Таблица 8.1

Побитовые операции

a

b

a|b

a&b

a^b

~a

1

1

1

1

0

0

0

1

1

0

1

1

1

0

1

0

1

0

0

0

0

0

0

1

Операция побитового логического отрицания (~) является унарной. В результате этой операции каждый бит, имеющий значение 1, становится равным 0 и наоборот. Данная операция называется также дополнением до единицы или инверсией.

Результатом операции сдвига влево (<<) является левый операнд, сдвинутый влево на число позиций, которое указано в правом операнде. Освобождающиеся младшие разряды заполняются нулями [24, 25]. Данная операция может применяться для умножения на число, равное степени числа 2, в соответствии с правилом:

x << n эквивалентно умножению х на 2 в степени n.

Результатом операции сдвига вправо (>>) является левый операнд, сдвинутый вправо на число позиций, которое указано в правом операнде. Освобождающиеся старшие разряды заполняются нулями для переменных типа unsigned либо значением старшего (знакового) бита для данных другого типа [24, 25]. Данная операция может применяться для деления на число, равное степени числа 2, в соответствии с правилом:

x >> n эквивалентно делению х на 2 в степени n.

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

Листинг 8.1. Для печати содержимого памяти, отведенной под переменную типа unsigned int, может быть использована функция, в которой создается массив, и элементы массива заполняются следующим образом:

  • Создается шаблон, содержащий единицу в старшем разряде.

  • Проверяется побитовое умножение исходного числа на шаблон и в массив заносится символ ‘1’, если это произведение отлично от нуля, и ‘0’ – в противном случае.

  • Затем шаблон сдвигается вправо на один бит.

  • Для более легкого чтения информации после каждых 8 битов в массив заносится пробел.

  • Операция повторяется до тех пор, пока шаблон отличен от нуля.

//L8_1.cpp

void print_bit(unsigned int x)

{

unsigned int sh=~0, i=0, k=0;

sh=~(sh>>1); //Шаблон с 1 в старшем разряде

char s[40];

while(sh>0)

{

s[i++]=sh&x?'1':'0';

k++;

if(k==8)

{

s[i++]=' ';

k=0;

}

sh>>=1; //Сдвиг шаблона в следующий разряд

}

s[i]='\0';

cout<<s<<'\n';

}

Для успешной проверки данной функции следует вводить числа в шестнадцатеричном виде, так как каждая шестнадцатеричная цифра представляется четырьмя двоичными разрядами.

Листинг 8.2. Программа печатает двоичное представление числа с использованием функции, приведенной в листинге 8.1.

//L8_2.cpp

#include <fstream>

#include <iostream>

using namespace std;

int main( )

{

setlocale(LC_CTYPE,"russian");

unsigned int n;

do

{

cout<<"Введите неотрицательное n ";

cin>>hex>>n; //Ввол числа в шестнадцатеричной

//системе счисления.

}while(n<0);

print_bit(n); //Печать числа в двоичной системе числения

cin.get();

cin.get();

return 0;

}

Результат работы программы листинга 8.2 приведен на рис. 8.1.

Рис. 8.1. Результат работы программы листинга 8.2

Листинг 8.3. В заданном числе инвертировать n битов с позиции k вправо. При вводе данных следует контролировать, чтобы позиция инвертируемого бита и количество инвертируемых битов не выходили за пределы числа. Для построения необходимо создать шаблон, содержащий 1 в инвертируемых позициях и 0 в остальных.

//L8_3.cpp

#include <stdio.h>

#include <tchar.h>

#include <iostream>

using namespace std;

void print_bit(unsigned int x);

int main( )

{

setlocale(LC_CTYPE,"russian");

unsigned int x, n, k, m, sh, y;

m=sizeof(unsigned int)*8;

do

{

cout<<"Введите неотрицательное x ";

cin>>hex>>x;

}while(x<0);

do

{

cout<<"Введите позицию k и число инвертируемых битов n ";

cin>>dec>>k>>n;

}while(!(k<=m&&n<=k));

print_bit(x);

sh=~0;

sh=((sh<<m-k)>>m-n)<<k-n;

y=~(x&sh)&sh;

x=x&(~sh)|y;

print_bit(x);

return 0;

}

void print_bit(unsigned int x)

{

unsigned int sh=~0,k=0,i=0;

char s[40];

sh=~(sh>>1);

cout<<'\n';

while(sh!=0)

{

s[i++]=(sh&x)?'1':'0';

k++;

if(k%8==0)

s[i++]=' ';

sh=sh>>1;

}

s[i]='\0';

cout<<s<<'\n';

}

На рис. 8.2 приведен результат выполнения программы листинга 8.3.

Рис. 8.2. Результат работы программы листинга 8.3

Побитовые операции можно использовать для укрупненного начертания слов. Укрупненное начертание какого-либо символа связано с заданием этого символа в виде таблицы [15]. Заполненные клетки таблицы образуют нужный контур символа. Содержимое такой таблицы можно закодировать с помощью 1 (клетка заполнена) и 0 (клетка не заполнена). Пусть такая таблица состоит из 7 × 5 элементов. Тогда для идентификации символа достаточно пяти семиразрядных двоичных чисел. Каждое из них будет кодировать один из пяти вертикальных слоев. Например, начертание символа “Н” кодируется следующими двоичными числами: 1111111 (первый и пятый вертикальные слои таблицы), 10 (второй, третий и четвертый слои таблицы). При этом переход от младших разрядов к старшим соответствует просмотру исходной таблицы сверху вниз (рис. 8.3).

Прямая со стрелкой 891

0

0

0

Прямая со стрелкой 881

Младший разряд

1

0

0

0

1

1

0

0

0

1

1

1

1

1

1

1

0

0

0

1

Прямая со стрелкой 85

Старший разряд

1

0

0

0

1

1

0

0

0

1

Рис. 8.3. Кодирование начертания символа “Н

Для распечатки символа необходимо установить, какие двоичные цифры находятся в соответствующих разрядах всех пяти чисел: 0 – печатать пробел, 1 – печатать выбранный символ.

Листинг 8.4. Вывести на экран дисплея укрупненное начертание слов: “ННГУ” и “МЕХМАТ”.

//L8_4.cpp

#include "stdafx.h"

#include <stdio.h>

#include <locale>

void _tmain()

{setlocale (LC_ALL, "Russian");

int i, j, k, n;

int B[6][5], D[6][5];

static char s[]="ННГУ", s2[]="МЕХМАТ";

char c, e;

for (n=0; (c=s[n])!='\0'; n++)

switch (c)

{

case 'Н': B[n][0]=B[n][4]=0177;

B[n][1]=B[n][2]=B[n][3]=010;

break;

case 'Г': B[n][0]=0177;

B[n][1]=B[n][2]=B[n][3]=01;

B[n][4]=03;

break;

case 'У': B[n][0]=047;

B[n][1]=B[n][2]=B[n][3]=0110;

B[n][4]=077;

break;

}

for (k=0; k<7; k++) // k – разряд

{ for (i=0; i<n; i++) // i – буква

{ j=0; // j - слой

do

{if (B[i][j] & 01) //Выделение k-го разряда каждого

//из чисел, кодирующих букву.

printf("%c", s[i]);

else

printf("%c", ' ');

B[i][j]=B[i][j]>>1; //Сдвиг вправо на одну позицию

//всех разрядов числа.

j++;

}

while (j<5);

printf("%s", " ");

}

printf ("\n");

}

printf ("\n");

for (n=0; (e=s2[n])!='\0'; n++)

switch (e)

{

case 'М': D[n][0]=D[n][4]=0177;

D[n][1]=D[n][3]=02;

D[n][2]=04;

break;

case 'Е': D[n][0]=0177;

D[n][1]=D[n][2]=D[n][3]=0111;

D[n][4]=0101;

break;

case 'Х': D[n][0]=D[n][4]=0143;

D[n][1]=D[n][3]=024;

D[n][2]=010;

break;

case 'А': D[n][0]=D[n][4]=0176;

D[n][1]=D[n][2]=D[n][3]=011;

break;

case 'Т': D[n][0]=D[n][1]=D[n][3]=D[n][4]=01;

D[n][2]=0177;

break;

}

for (k=0; k<7; k++)

{ for (i=0; i<n; i++)

{ j=0;

do {

if (D[i][j] & 01) //Выделение k-го разряда каждого

//из чисел, кодирующих букву.

printf("%c", s2[i]);

else

printf("%c", ' ');

D[i][j] = D[i][j] >> 1; //Сдвиг вправо на одну позицию

//всех разрядов числа.

j++;

}

while (j<5);

printf("%s", " ");

}

printf ("\n");

}

printf ("\n");

}

Результат выполнения программы листинга 8.4 приведен на рис. 8.4.

Рис. 8.4. Результат работы программы листинга 8.4

Упражнения

  1. Написать функцию, заменяющую n правых битов числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  2. Написать функцию, заменяющую n левых битов числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  3. Написать функцию, заменяющую n правых битов числа x на n правых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

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

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

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

  7. Написать функцию, заменяющую n левых битов числа x на n левых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  8. Написать функцию, заменяющую n битов с позиции p числа x на n правых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  9. Написать функцию, заменяющую n левых битов числа x на n правых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

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

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

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

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

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

  15. Написать функцию, заменяющую n битов с позиции p числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  16. Написать функцию, заменяющую n битов с позиции p числа x на n левых инвертированных битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  17. Написать функцию, заменяющую n битов с позиции p числа x на инвертированные. Провести вычисление для заданного числа x и заданного количества битов n. Результат записать в файл.

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

  19. Написать функцию, заменяющую n битов с позиции p числа x на n левых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  20. Написать функцию, заменяющую n битов с позиции p числа x на n правых битов числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  21. Написать функцию, определяющую количество битов, значение которых в двоичном представлении чисел x и y совпадают. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  22. Написать функцию, определяющую количество битов, значение которых в двоичном представлении чисел x и y не совпадают. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  23. Написать функцию, определяющую разность между количеством единиц в двоичном представлении чисел x и y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  24. Написать функцию, определяющую разность между количеством нулей в двоичном представлении чисел x и y. Провести вычисление для заданных чисел x и y. Результат записать в файл.

  25. Написать функцию, заменяющую n левых битов числа x на n битов с позиции p числа y. Провести вычисление для заданных чисел x и y. Результат записать в файл.