Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Turbo Pascal] Побитовые операции 
V
    Опции темы
Dower
Дата 9.2.2010, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.1.2010

Репутация: нет
Всего: нет



Задача: Циклически сдвинуть двоичные разряды числа на пять позиций влево.
Для примера дана программа, задачу надо решить на основе этой пргграммы.


Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  POBIT.PAS 0,33 Kb
PM MAIL   Вверх
Dancer
Дата 9.2.2010, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 4
Всего: 37



Код

function pow2(A:byte):Integer;
var result: Integer;
    i: Integer;
begin
  result := 1;
  for i:=1 to A do
    result := result * 2;
  pow2 := result;
end;

procedure Print_binary (d: word);
var 
  mask: word; 
  i: 1..16; 

begin 
  mask:=$8000; 
  for i:=1 to 16 do begin 
    if d and mask=0 then
     write (0) 
    else 
     write (1);

    mask:=mask shr 1; 
  end;

  writeln;
  writeln; 
end; 

function cyclicShiftLeft(number: word; cyclicBitsLeft: byte):word;
var
    mask :Integer;
    x,y :word;

begin
    cyclicBitsLeft := cyclicBitsLeft mod 16;
    mask := pow2(16) - pow2(16 - cyclicBitsLeft);
    x := number and mask;
    x := x shr (16 - cyclicBitsLeft);
    y := number shl cyclicBitsLeft;
    cyclicShiftLeft := y or x;
end;

Var
  a,c: word;
begin
  a:=52;
  write ('a= ');
  Print_binary (a);
  c:= cyclicShiftLeft(a, 5);
  write ('a = ');
  Print_binary (c);
  readln;
end.



--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
Dower
Дата 9.2.2010, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.1.2010

Репутация: нет
Всего: нет



Спасибо, работает.

PM MAIL   Вверх
Dower
Дата 9.2.2010, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.1.2010

Репутация: нет
Всего: нет



А можно краткие пояснения кода.
PM MAIL   Вверх
Dower
Дата 24.2.2010, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.1.2010

Репутация: нет
Всего: нет



А можно краткие пояснения кода. Очень надо.
PM MAIL   Вверх
Dancer
Дата 25.2.2010, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 4
Всего: 37



function cyclicShiftLeft(number: word; cyclicBitsLeft: byte):word;
var
    mask :Integer;
    x,y :word;

begin
    cyclicBitsLeft := cyclicBitsLeft mod 16;
    mask := pow2(16) - pow2(16 - cyclicBitsLeft);
    x := number and mask;
    x := x shr (16 - cyclicBitsLeft);
    y := number shl cyclicBitsLeft;
    cyclicShiftLeft := y or x;
end;

Циклически нужно двинуть биты влево, на числах, которые занимают 2 байта (то есть 16 бит).
Это делает функция: function cyclicShiftLeft(number: word; cyclicBitsLeft: byte):word;
16 бит взята потому, что такое значение пользовалось для печати значения числа в двоичном виде(код топик_стартера): procedure Print_binary (d: word);

1. Так как циклически двигаются биты в 16 битовом числе, то берём остаток от деления на 16 числа, которое передаются в функцию (cyclicBitsLeft), это число не может быть более 255, так как тип описан как byte.
    cyclicBitsLeft := cyclicBitsLeft mod 16;
Получив остаток от деления, получаем число, на сколько бит действительно нужно будет делать левый сдвиг.

2. Дале получаем маску, по которой вытаскиваем биты, которые у нас цикличиски перейдут в конец получаемого числа.
Для этого нам нужно из 2 в степени 16 вычесть число 2 в степени (16 - количество бит, на которе делается левый сдвиг)
    mask := pow2(16) - pow2(16 - cyclicBitsLeft);

3. Делаем логическое умножение нашего "входного" числа с маской, то есть выделяем те биты, которые после выполнения операции левого сдвига должны будут оказаться вконце нашего результирующего числа (советую порисовать на бумажке представление чисел в двоичной форме и подвигать их самостоятельно)
Получаем число:     x := number and mask;

4. Далее выполняем правый сдвиг числа x на нужное количество бит (16 - (количество_бит_левого_сдвига mod 16))
то есть, биты слева будут заполнены нулями, а наши битики из числа взятые по маске двигаются в конец числа x.
    x := x shr (16 - cyclicBitsLeft);

5. Далее нужно подвинуть битики нашего "входного" числа влево, заполняя нулями правые сдвинутые биты.
    y := number shl cyclicBitsLeft;

6. Тепеть нужно логически сложить числа x и y, чтобы получить результат, и вернуть этот результат из функции.
    cyclicShiftLeft := y or x;

Всё. Ловкость рук и никакого мошенства! smile

Пример:
входное число 52, сдвигаем на 11 бит циклически влево.
c:= cyclicShiftLeft(a, 11);

Запишим число a в двоичном виде (не забываем, что у нас числа 16 битные): 0000000000110100
получаем маску, по которой нужно сохранить число, то есть старшие биты, чтобы их передвинуть в конец результирующего числа.
mask=pow2(16) - pow2(16-11)=65536-32=0xFFE0 (в двоичном виде: 1111111111100000)
теперь делаем логическое умножение:
      0000000000110100 (number)
AND
      1111111111100000 (mask)
      ==============
      0000000000100000 (x)
то есть, x у нас теперь равно 32, или 0x0020: (0000000000100000)

теперь передвигаем число x вправо на (16-11) бит это равносильно тому, что мы бы эти биты циклически подвинули влево на 11 бит.
  x := x shr 5; 
слева будет заполено нулями, то есть получаем: x = 1, или 0x0001 (0000000000000001)


теперь передвигаем "входное" число на 11 бит влево, справа заполняя нулями.
    y := number shl 11;       0000000000110100 (number) << 11
    y = 40960, или 0xA000 (1010000000000000)

теперь логически складываем эти два числа:
      1010000000000000 (y)
OR
      0000000000000001 (x)
      ==============
      1010000000000001 (результат)  40961 или 0xA001




--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
Dower
Дата 25.2.2010, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.1.2010

Репутация: нет
Всего: нет



Огромное вам спасибо
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0444 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.