我写了一个程序来计算不同精度的方程根。 4种不同的方法。 我使用PascalABC。
所以,问题是:当我想看输出时,程序只显示4个方法的结果。订单不会影响输出结果,也不会影响文件\控制台输出。 我完全不知道该怎么做,这是我第一次遇到这个问题。至少在Pascal。 这是代码:
uses crt;
type
pint = ^integer;
aptr = ^real;
bptr = ^real;
xpreal = array[1..6] of real;
npint = array[1..6] of integer;
function fun(x:real): real;
begin fun := x * x * x + x * x - 3; end;
function dfdx(x:real): real;
begin dfdx := 3 * x * x + 2 * x end;
function fi(x:real): real;
begin fi := sqrt(3 / (x + 1)) end;
function half(a, b, eps:real; n:pint):real;
var
x:real;
begin
n^ := 0;
repeat
x := (a + b) / 2;
n^ := n^ + 1;
if (fun(a) * fun(x) >= 0) then
a := x
else
b := x;
until abs(fun(x)) < eps;
half := x;
end;
function def(b, eps:real; n:pint):real;
var
x: real;
begin
x := b;
n^ := 0;
repeat
x := x - fun(x) / dfdx(x);
n^ := n^ + 1;
until abs(fun(x)) < eps;
def := x;
end;
function itr(a: aptr; b: bptr): real;
var
x: real;
begin
x := fun(a^) * (a^-b^) / (fun(b^) - fun(a^)) + a^;
if fun(x) * fun(a^) >= 0 then a^ := x else a^ := a^;
if fun(x) * fun(b^) >= 0 then b^ := x else b^ := b^;
itr := x;
end;
function hord(a, b, eps:real; n:pint):real;
begin
n^ := 0;
while(abs(fun(itr(@a, @b))) > eps) do
begin
n^ := n^ + 1;
end;
hord := itr(@a, @b);
end;
function iter(b, eps:real; n:pint):real;
var
x: real;
begin
n^ := 0;
x := b;
repeat
x := fi(x);
n^ := n^ + 1;
until abs(fun(x)) < eps;
iter := x;
end;
procedure graph(var inf: text; x:xpreal; n: npint; c: integer);
var
i,j:integer;
eps: real;
begin
eps := 0.01;
writeln(inf);
write(inf, 'eps= ');
for i := 1 to c do
begin
write(inf, eps:6:7, ' ');
eps := eps * 0.1;
end;
writeln(inf); write(inf, 'x = ');
for i := 1 to c do
begin
write(inf, x[i]:8:7,' ');
end;
writeln(inf); writeln(inf);
writeln(inf, '^N'); writeln(inf);
for i := n[c-1] downto 0 do
begin
writeln(inf, '|');
for j := 1 to c do
if (n[j] = i) then
write(inf, '<*>')
else write(inf, ' ');
writeln(inf);
end;
writeln(inf, '+------------------------------------> eps');
writeln(inf);
eps := 0.01;
for i := 1 to 6 do
begin
write(inf, 'EPS = : ', eps:6:7);
for j := 0 to n[i] do
write(inf,'* ');
write(inf,n[i]);
writeln(inf);
eps := eps * 0.1;
end;
writeln(inf, '__________________________');
end;
var
a, b, eps : real;
i : integer;
x : xpreal;
n : npint;
inf : text;
begin
a := 0.6;
b := 1.4;
eps := 0.01;
assign(inf,'C:\My Documents\Pas\output.txt');
rewrite(inf);
for i := 1 to 6 do //1-st output
begin
x[i] := half(a, b, eps, @n[i]);
eps := eps * 0.1;
end;
writeln(inf, 'half-seg-method');
graph(inf, x, n, 6);
for i := 1 to 6 do //2-nd output
begin
x[i] := def(b, eps, @n[i]);
eps := eps * 0.1;
end;
writeln(inf, 'Newton-method');
graph(inf, x, n, 6);
for i := 1 to 6 do //3-rd output
begin
x[i] := iter(b, eps, @n[i]);
eps := eps * 0.1;
end;
writeln(inf, 'iter-method');
graph(inf, x, n, 6);
for i := 1 to 6 do //4-th output
begin
x[i] := hord(a, b, eps, @n[i]);
eps := eps * 0.1;
end;
writeln(inf, 'hord-method');
graph(inf, x, n, 6);
close(inf);
end.
答案 0 :(得分:0)
您的代码存在很多问题:
首先:主要的错误是由于编码你想要不可能的精度
错误。您忘记在每次循环之前将eps
重置为0.01,因此您使用eps=1e-8
启动六个牛顿部分并将其结束
与eps=1e-14
等
eps := 0.01;
for i := 1 to 6 do {3-rd output}
begin
x[i] := iter(b, eps, @n[i]);
eps := eps * 0.1;
end;
writeln(inf, 'iter-method');
graph(inf, x, n, 6);
eps := 0.01;
for i := 1 to 6 do {4-th output}
....
第二个问题是您的收敛测试可能会因绝对错误标准而失败。通常我们使用相对错误测试,例如为你的牛顿:
function def(b, eps:real; n:pint):real;
var
x: real;
d: real;
begin
x := b;
n^ := 0;
repeat
d := fun(x) / dfdx(x);
x := x - d;
n^ := n^ + 1;
until abs(d) < eps*abs(x);
def := x;
end;
这另外显示了编码风格的另一个问题。您可以使用相同的参数反复评估函数,而不是将函数值存储在局部变量中:对于简单函数来说,这可能几乎没有问题,但是对于更复杂的函数来说非常昂贵且无效。
在你的function itr(a: aptr; b: bptr): real;
而不是三个函数调用中,你做的更强烈七!
...