Алгебра у программистов. Преподаватель пишет на доске: sin X = 1.
- Ну, кто может найти X?
Выбегает программист и так радостно:
- Вот, вот X, - показывает на X.
Это может звучать тривиально, но как мне возвести число в степень? Например,
2^12 = 4095.
На самом деле вопрос далеко не тривиальный. Проблема в том, что сам алгоритм
функции далеко не прост. Функцией Power(X, N) (т.е. X^N) должны четко
отслеживаться несколько возможных ситуаций:
X любое число, N = 0
X = 1, N любое число
X = 0 и N > 0
X = 0 и N < 0
X > 0
X < 0 и N нечетное целое
X < 0 и N целое
X < 0 и N нецелое
Посмотрите на следующую, абсолютно правильно
работающую функцию (тем не менее она может быть и не самой эффективной!):
interfacetype
EPowerException = class(Exception)
end;
implementationfunction Power(X, N: real): extended;
var
t: longint;
r: real;
isInteger: boolean;
beginif N = 0 thenbegin
result := 1.0;
exit;
end;
if X = 1.0 thenbegin
result := 1.0;
exit;
end;
if X = 0.0 thenbeginif N > 0.0 thenbegin
result := 0.0;
exit;
endelseraise EPowerException.Create('Результат - бесконечность');
end;
if (X > 0) thentry
result := exp(N * ln(X));
exit;
exceptraise
EPowerException.Create('Результат - переполнение или потеря значимости');
end;
{ X - отрицательный, но мы все еще можем вычислить результат, если n целое. }{ пытаемся получить целую часть n с использованием типа longint, вычисление }{ четности n не займет много времени }try
t := trunc(n);
if (n - t) = 0 then
isInteger := trueelse
isInteger := False;
except{ Лишний бит может вызвать переполнение или потерю значимости }
r := int(n);
if (n - r) = 0 thenbegin
isInteger := true;
if frac(r / 2) = 0.5 then
t := 1
else
t := 2;
endelse
isInteger := False;
end;
if isInteger thenbegin{n целое}if odd(t) then{n нечетное}try
result := -exp(N * ln(-X));
exit;
exceptraise
EPowerException.Create('Результат - переполнение или потеря значимости');
endelse{n четное}try
result := exp(N * ln(-X));
exit;
exceptraise
EPowerException.Create('Результат - переполнение или потеря значимости');
end;
endelseraise EPowerException.Create('Результат невычисляем');
end;
Перевод текста на русский язык:
Приведенный код Delphi - это реализация функции Power, которая вычисляет значение X в степени N, где X и N - вещественные числа.
Вот разбивка кода:
Функция сначала проверяет некоторые специальные случаи:
Если N равен 0, результат всегда равен 1.
Если X равен 1, результат всегда равен 1,regardless of N.
Если X равен 0 и N положителен, результат равен 0.
Если X равен 0 и N отрицателен, функция выбрасывает исключение с сообщением о том, что результат является бесконечностью (поскольку любая степень 0 не определена).
Функция затем проверяет, является ли X больше 0:
Если это так, функция использует экспоненциальную функцию (exp) для вычисления результата, где N умножается на натуральный логарифм X. Это делается с помощью блока try-except для обработки потенциальных переполнений или потери значимости.
Если X меньше 0 и N целое:
Функция пытается вычислить результат следующим образом:
Если N четное, функция использует экспоненциальную функцию с -X и N умноженным на натуральный логарифм -X.
Если N нечетно, функция использует экспоненциальную функцию с -X и N умноженным на натуральный логарифм -X, но с изменением знака (т.е., отрицательный результат).
Если X меньше 0 и N не целое:
Функция выбрасывает исключение с сообщением о том, что результат не определен.
Код также включает в себя некоторые ошибки обработки и краевые случаи, такие как проверка на переполнение или потерю значимости при вычислении результата с помощью экспоненциальной функции.
В качестве альтернативных решений предлагаются следующие предложения:
Использовать логарифмический подход: вместо прямого вычисления X в степени N, можно использовать свойства логарифмов для вычисления результата более эффективным образом.
Реализовать рекурсивное решение: рекурсивная реализация может быть использована для вычисления результата,although она может не быть так эффективной как итеративный подход.
Использовать функцию библиотеки: Delphi предоставляет встроенную функцию Power, которая может быть использована для вычисления степеней чисел.
В целом, этот код - хороший пример того, как обрабатывать краевые случаи и ошибки обработки в реализации математической функции.
В статье описывается алгоритм возведения числа в степень, учитывающий различные ситуации, возникающие при вычислении, таких как целые и нецелые степени, отрицательные основания и степени.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.