Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [Turbo Pascal] Побитовые операции


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

Автор: Dancer 9.2.2010, 13:31
Код

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.

Автор: Dower 9.2.2010, 13:42
Спасибо, работает.

Автор: Dower 9.2.2010, 21:24
А можно краткие пояснения кода.

Автор: Dower 24.2.2010, 15:43
А можно краткие пояснения кода. Очень надо.

Автор: Dancer 25.2.2010, 17:19
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


Автор: Dower 25.2.2010, 22:24
Огромное вам спасибо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)