Меню

Главная

Статистика

 

 


Пример #2.

Если в языке программирования отсутствует операция возведения в степень, то программист вынужден сам писать соответствующую процедуру.

Вычислить am (a, m - натуральные числа; будем считать, что вычисляемое значение помещается в 4 байта памяти для целочисленных типов).

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

Очевидный вариант: на каждом шаге цикла умножений участвуют два сомножителя - значение "уже сосчитанного произведения" и "оставшееся", содержащее показатель степени. Показатель степени второго сомножителя уменьшается на 1, а первый сомножитель, соответственно, умножается на основание степени. Ясно, что начав со значения 1 для первого сомножителя, цикл потребует число шагов, равное значению показателя степени m.

Хотелось бы уменьшить количество умножений. Это удается, если воспользоваться следующим свойством операции возведения в степень:
am=(am/2)2 при четных m, am=a(a(m-1)/2)2 при нечетных m.

Следуя ему, получаем улучшенный вариант: будем на каждом шаге до "обнуления" показателя степени

  • при нечетном значении показателя степени второго сомножителя - домножать первый сомножитель на значение основания степени второго сомножителя; уменьшать на 1 и затем делить пополам сам показатель;

  • при четном значении - возводить во вторую степень основание второго сомножителя, уменьшая при этом вдвое показатель степени.

Проиллюстрируем механизм предлагаемого алгоритма на примере. Пусть в качестве показателя степени предложено значение m=15.
am=a15=a1+14 =(a)*(a2)7=(a)*(a2)1+6 =(a*a2)*(a2)6 =(a*a2)*(a2)2*3 =(a*a2)*((a2)2)3 =(a*a2)*((a2)2)1+2 =(a*a2*(a2)2)*((a2) 2)2

Описанный механизм называется дихотомическим алгоритмом возведения в степень. (Заметим, кстати, что с применением дихотомии, то есть деления пополам, нам еще не однажды придется встретиться в других алгоритмах.)

С точки зрения двоичной арифметики, идея особенно плодотворна, поскольку возведение в степень 2 легко реализуется сдвигом аргумента на один бит влево, а деление на 2 - сдвигом вправо. Теперь несложно написать соответствующую процедуру.

function Power (a, m : byte) : longint;
var
  _a : longint;  {текущее значение основания степени}
  _m : byte;     {текущее значение показателя степени}
  p  : longint;  {текущее значение накопленного
                                   произведения}
begin
  if  m = 0  then
    begin
      Power := 1;
      Exit
    end;
  p := 1;
  _a := a;
  _m := m;
  while  _m > 0  do
    begin
      if  _m and 1 = 1 then  p := p * _a;
      _a := _a * _a;
      _m := _m shr 1;
    end;
  Power := p
end;
                

Этот вариант функции вычисляет значение степени только для неотрицательных значениях аргументов. Более широкий диапазон входных значений позволит обрабатывать функция, написать которую предлагает

Назад

лазерная гравировка и лазерное фото и сувениры из стекла. предложение лета! Новые цены: система управления сайтом ну или cms только здесь! Теперь.. недвижимость снять комнату квартиры. aстрофорум vbulletin