Tak jak zasugerowałeś próbowałem uzupełniać zerami ale nic z tego nie wyszło
Moduł do obsługi wielomianów
Kopiuj
unit Polynomial;
interface
uses math;
const ZERO = 1e-10;
type TPolynomial = record
deg:integer;
coeff:array of Double
end;
function MakePolynomial(n:integer):TPolynomial;
function Equals(a,b:TPolynomial):boolean;
function AddPolynomials(a,b:TPolynomial):TPolynomial;
function SubtractPolynomials(a,b:TPolynomial):TPolynomial;
function MultiplyPolynomials(a,b:TPolynomial):TPolynomial;
function DividePolynomials(a,b:TPolynomial;var r:TPolynomial):TPolynomial;
function Horner(p:TPolynomial;x:Double):Double;
procedure WritePolynomial(p:TPolynomial;c:char);
implementation
function MakePolynomial(n:integer):TPolynomial;
var p:TPolynomial;
begin
p.deg := n;
SetLength(p.coeff,n+1);
MakePolynomial := p
end;
procedure FindDeg(var p:TPolynomial);
var i:integer;
begin
for i := p.deg downto 0 do
if abs(p.coeff[i]) > ZERO then
begin
p.deg := i;
Exit;
end;
p.deg := 0
end;
function AddPolynomials(a,b:TPolynomial):TPolynomial;
var newDeg,range,i:integer;
n:TPolynomial;
begin
if a.deg > b.deg then
newDeg := a.deg
else
newDeg := b.deg;
range := newDeg - abs(a.deg - b.deg);
n := MakePolynomial(newDeg);
for i := range downto 0 do
n.coeff[i] := a.coeff[i] + b.coeff[i];
if a.deg > b.deg then
for i := newDeg downto range+1 do
n.coeff[i] := a.coeff[i]
else
for i := newDeg downto range+1 do
n.coeff[i] := b.coeff[i];
findDeg(n);
AddPolynomials := n
end;
function SubtractPolynomials(a,b:TPolynomial):TPolynomial;
var newDeg,range,i:integer;
n:TPolynomial;
begin
if a.deg > b.deg then
newDeg := a.deg
else
newDeg := b.deg;
range := newDeg - abs(a.deg - b.deg);
n := MakePolynomial(newDeg);
for i := range downto 0 do
n.coeff[i] := a.coeff[i] - b.coeff[i];
if a.deg > b.deg then
for i := newDeg downto range+1 do
n.coeff[i] := a.coeff[i]
else
for i := newDeg downto range+1 do
n.coeff[i] := -b.coeff[i];
findDeg(n);
SubtractPolynomials := n
end;
function MultiplyPolynomials(a,b:TPolynomial):TPolynomial;
var i,j:integer;
n:TPolynomial;
begin
n := MakePolynomial(a.deg + b.deg);
for i := 0 to n.deg do
n.coeff[i] := 0;
for i := 0 to a.deg do
for j := 0 to b.deg do
n.coeff[i + j] := n.coeff[i + j] + a.coeff[i] * b.coeff[j];
MultiplyPolynomials := n
end;
function DividePolynomials(a,b:TPolynomial;var r:TPolynomial):TPolynomial;
var q,temp:TPolynomial;
i,j,qdeg:integer;
begin
if a.deg < b.deg then
qdeg := 0
else
qdeg := a.deg;
q := MakePolynomial(qdeg);
if q.deg = 0 then
begin
q.coeff[0] := 0;
r.deg := a.deg;
for i :=r.deg downto 0 do
r.coeff[i] := a.coeff[i];
DividePolynomials := q;
Exit
end;
temp := MakePolynomial(a.deg);
for i := 0 to a.deg do
begin
temp.coeff[i] := a.coeff[i];
q.coeff[i] := 0
end;
for i := a.deg - b.deg downto 0 do
begin
q.coeff[i] := temp.coeff[b.deg + i] /b.coeff[b.deg];
for j := b.deg + i - 1 downto i do
temp.coeff[j] := temp.coeff[j] - q.coeff[i] * b.coeff[j - i]
end;
for i := 0 to b.deg - 1 do
r.coeff[i] := temp.coeff[i];
if r.deg < a.deg then
for i := b.deg to r.deg do
r.coeff[i] := 0
else
for i := b.deg to a.deg do
r.coeff[i] := 0;
findDeg(r);
findDeg(q);
DividePolynomials := q
end;
function Equals(a,b:TPolynomial):boolean;
var bool : boolean;
i : integer;
begin
bool := a.deg = b.deg;
i := a.deg;
while bool and (i >= 0) do
begin
bool := bool and (a.coeff[i] = b.coeff[i]);
Dec(i)
end;
Equals := bool
end;
procedure WritePolynomial(p:TPolynomial;c:char);
var i:integer;
begin
for i := p.deg downto 0 do
if p.coeff[i] < 0 then
write(p.coeff[i]:1:12,'*',c,'^',i)
else
write('+',p.coeff[i]:1:12,'*',c,'^',i);
writeln
end;
function Horner(p:TPolynomial;x:Double):Double;
var v:double;
i:integer;
begin
v := p.coeff[p.deg];
for i := p.deg - 1 downto 0 do
v := v * x + p.coeff[i];
Horner := v
end;
begin
end.
Kod programu do testowania funkcji realizującej algorytm Karacuby
Kopiuj
program untitled;
uses crt,math,polynomial;
function Karatsuba(f,g:TPolynomial):TPolynomial;
var temp1,temp2:TPolynomial;
h,h1,h2,h3:TPolynomial;
k,d:integer;
begin
if ((f.deg = 0)and(f.coeff[0] = 0)) or ((g.deg = 0)and(g.coeff[0] = 0)) then
begin
h := makePolynomial(0);
h.coeff[0] := 0;
Karatsuba := h;
Exit
end;
if ((f.deg = 0) and (g.deg = 0)) then
begin
h := makePolynomial(0);
h.coeff[0] := f.coeff[0] * g.coeff[0];
Karatsuba := h;
Exit
end;
begin
d := max(f.deg,g.deg);
d := Ceil(0.5 * d);
temp1 := makePolynomial(d-1);
for k := 0 to min(d - 1,f.deg) do
temp1.coeff[k] := f.coeff[k];
for k := min(d-1,f.deg) + 1 to d - 1 do
temp1.coeff[k] := 0;
temp2 := makePolynomial(d-1);
for k := 0 to min(d - 1,g.deg) do
temp2.coeff[k] := g.coeff[k];
for k := min(d - 1,g.deg) + 1 to d - 1 do
temp2.coeff[k] := 0;
h1 := Karatsuba(temp1,temp2);
temp1 := makePolynomial(ord((f.deg - d)>=0)*(f.deg - d));
for k := 0 to temp1.deg do
temp1.coeff[k] := f.coeff[k + d];
temp2 := makePolynomial(ord((g.deg - d)>=0)*(g.deg - d));
for k := 0 to temp2.deg do
temp2.coeff[k] := g.coeff[k+d];
h2 := Karatsuba(temp1,temp2);
temp1 := makePolynomial(d-1);
temp2 := makePolynomial(ord((g.deg - d)>=0)*(g.deg - d));
for k := 0 to min(d - 1,g.deg) do
temp1.coeff[k] := g.coeff[k];
for k := min(d - 1,g.deg) + 1 to d-1 do
temp1.coeff[k] := 0;
for k := 0 to temp2.deg do
temp2.coeff[k] := g.coeff[k+d];
h3 := AddPolynomials(temp1,temp2);
for k := 0 to min(d - 1,f.deg) do
temp1.coeff[k] := f.coeff[k];
for k := min(d - 1,f.deg) + 1 to d - 1 do
temp1.coeff[k] := 0;
temp2 := makePolynomial(ord((f.deg - d)>=0)*(f.deg - d));
for k := 0 to temp2.deg do
temp2.coeff[k] := f.coeff[k+d];
temp1 := AddPolynomials(temp1,temp2);
h3 := Karatsuba(temp1,h3);
temp1 := SubtractPolynomials(h3,h1);
temp1 := SubtractPolynomials(temp1,h2);
temp2 := makePolynomial(temp1.deg+d);
for k := 0 to temp1.deg do
temp2.coeff[k + d] := temp1.coeff[k];
for k := 0 to d - 1 do
temp2.coeff[k] := 0;
h := AddPolynomials(h1,temp2);
temp2 := makePolynomial(h2.deg + 2*d);
for k := 0 to h2.deg do
temp2.coeff[k + 2*d] := h2.coeff[k];
for k := 0 to 2*d - 1 do
temp2.coeff[k] := 0;
h := AddPolynomials(h,temp2);
Karatsuba := h;
end;
end;
var f:text;
k,n,m:integer;
a,b,c:TPolynomial;
BEGIN
Assign(f,'input.txt');
Reset(f);
ReadLn(f,n);
a := makePolynomial(n);
k := n;
while not Eoln(f) do
begin
Read(f,a.coeff[k]);
k:=k-1;
end;
ReadLn(f,m);
b := makePolynomial(m);
k := m;
while not Eoln(f) do
begin
Read(f,b.coeff[k]);
k:=k-1;
end;
WriteLn('Polynomial a');
WriteLn(a.deg);
writePolynomial(a,'x');
WriteLn('Polynomial b');
WriteLn(b.deg);
writePolynomial(b,'x');
c := Karatsuba(a,b);
WriteLn('Polynomial c');
WriteLn(c.deg);
writePolynomial(c,'x');
Close(f);
END.
Podobno błąd zakresu jest gdzieś w linii 42