БОЛЬШОЙ FAQ ПО DELPHI



Возведение числа в степень

Алгебра у программистов. Преподаватель пишет на доске: sin X = 1.
- Ну, кто может найти X?
Выбегает программист и так радостно:
- Вот, вот X, - показывает на X.

Это может звучать тривиально, но как мне возвести число в степень? Например, 2^12 = 4095.

На самом деле вопрос далеко не тривиальный. Проблема в том, что сам алгоритм функции далеко не прост. Функцией Power(X, N) (т.е. X^N) должны четко отслеживаться несколько возможных ситуаций:

  1. X любое число, N = 0
  2. X = 1, N любое число
  3. X = 0 и N > 0
  4. X = 0 и N < 0
  5. X > 0
  6. X < 0 и N нечетное целое
  7. X < 0 и N целое
  8. X < 0 и N нецелое

Посмотрите на следующую, абсолютно правильно работающую функцию (тем не менее она может быть и не самой эффективной!):


 interface
 
 type
   EPowerException = class(Exception)
   end;
 
 implementation
 
 function Power(X, N: real): extended;
 var
   t: longint;
   r: real;
   isInteger: boolean;
 begin
   if N = 0 then
   begin
     result := 1.0;
     exit;
   end;
 
   if X = 1.0 then
   begin
     result := 1.0;
     exit;
   end;
 
   if X = 0.0 then
   begin
     if N > 0.0 then
     begin
       result := 0.0;
       exit;
     end
     else
       raise EPowerException.Create('Результат - бесконечность');
   end;
 
   if (X > 0) then
   try
     result := exp(N * ln(X));
     exit;
   except
     raise
       EPowerException.Create('Результат - переполнение или потеря значимости');
   end;
 
   { X - отрицательный, но мы все еще можем вычислить результат, если n целое. }
   { пытаемся получить целую часть n с использованием типа longint, вычисление }
   { четности n не займет много времени }
 
   try
     t := trunc(n);
     if (n - t) = 0 then
       isInteger := true
     else
       isInteger := False;
   except
     { Лишний бит может вызвать переполнение или потерю значимости }
     r := int(n);
     if (n - r) = 0 then
     begin
       isInteger := true;
       if frac(r / 2) = 0.5 then
         t := 1
       else
         t := 2;
     end
     else
       isInteger := False;
   end;
 
   if isInteger then
   begin
     {n целое}
     if odd(t) then
       {n нечетное}
     try
       result := -exp(N * ln(-X));
       exit;
     except
       raise
         EPowerException.Create('Результат - переполнение или потеря значимости');
     end
     else
       {n четное}
     try
       result := exp(N * ln(-X));
       exit;
     except
       raise
         EPowerException.Create('Результат - переполнение или потеря значимости');
     end;
   end
   else
     raise EPowerException.Create('Результат невычисляем');
 end;
 




<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ



Материалы находятся на сайте https://exelab.ru/pro/



Видеокурс ВЗЛОМ