скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

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



Алгебра у программистов. Преподаватель пишет на доске: 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;






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook