В: Это может звучать тривиально, но как мне возвести число в
степень? Например, 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 нецелое
Посмотрите на следующую, абсолютно правильно
работающую функцию (тем не менее она может быть и не самой эффективной!):
|
|
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; | |