- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
Procedure MakeChain(x: real; var a: array of word); (* Процедура раскладывает вещественное число в цепную дробь *)
var
i: byte;
begin
i:=0;
Repeat
a[i]:=Int(x); x:=1/(x-a[i]); i:=i+1
Until (abs(1/x) < epsilon) or (Int(x) = 0) (* NB! *)
end;
Procedure MakeFrac(a: array of word; var AN, BN: word); (* Процедура собирает обыкновенную дробь из цепной дроби *)
var
i: byte; AP, BP: word; temp: word;
begin
AN:=1; AP:=0; BN:=a[1]; BP:=1; i:=2;
Repeat
temp:=AN; AN:=AN*a[i]+AP; AP:=temp;
temp:=BN; BN:=BN*a[i]+BP; BP:=temp;
i:=i+1
Until a[i] = 0 (* NB! *)
end;
Function PowerInt(x: real; p: longint): real; (* возведение числа в целую степень *)
var
R: real;
begin
R:=1; if p<0 then x:=1/x; p:=abs(p);
Repeat
if p and 1 = 1 then R:=R*x;
p:=p shr 1;
if p<>0 then x:=sqr(x)
Until p=0;
PowerInt:=R
end;
Function Power(x: real; p: real): real;
var
y: real;
z: array[0..16000 div sizeof(word)] of word;
a, b: word;
begin
y:=PowerInt(x, Trunc(p)) * exp(Frac(p) * ln(abs(x)));
if x<0 then
begin
MakeChain(Frac(p), z);
MakeFrac(z, a, b);
if Odd(b) then
begin
if Odd(a) then y:=-y (* если числитель и знаменатель показателя степени нечётные, меняем знак результата *)
end
else
begin
(* NB! В случае чётного знаменателя показателя степени результат комплексный. Забьём на это *)
end
end;
Power:=y
end;
Инновационный алгоритм, написанный мной лет 12 тому назад, позволяющий возводить отрицательные числа в дробную степень.
Жанру сайта вполне соответствует, то есть не без говнокода.
guest 23.12.2010 09:21 # +4
Ваш К.О.
inkanus-gray 23.12.2010 17:39 # +1
Lure Of Chaos 24.12.2010 01:27 # +4
-
ассистент кэпа
guest 23.12.2010 09:23 # −1
Особенно здесь:
inkanus-gray 23.12.2010 17:38 # 0
Веселье, по крайней мере, здесь:
1. Первые две процедуры можно сшить в одну, и тогда массив больше не нужен.
2. Нужен более адекватный критерий завершения разложения в цепную дробь. Если a и b становятся большими, продолжать разложение нет смысла.
Был ещё один вариант 39-й строки:
Lure Of Chaos 24.12.2010 01:28 # 0
> Until (abs(1/x) < epsilon) or (Int(x) = 0)
TarasB 24.12.2010 11:14 # 0
Lure Of Chaos 24.12.2010 14:17 # 0
TarasB 24.12.2010 14:20 # 0
abs(1/x) < epsilon - это значит, что икс по модулю мегабольшое
Int(x) = 0 - это значит, что икс по модулю меньше 1/2
Lure Of Chaos 24.12.2010 14:28 # 0