Турбо Паскаль 7.0, посмотрите правильность решения задачки

FasterHarder
Дата: 15.11.2007 13:17:07
I started in 1983, in 2007 i still on a case!

Всем программистам привет! Respect! В общем есть малая задачка, которую я уже сделал, но нет уверенности, что сделал правильно, т к результаты которые получаю не сходятся с ответами. Кому не лень, посмотрите, где закралась ошибка:). Вот условие:
написать процедуру, которая вычисляет функцию F(x) при |x| < 1 с точностью до |x| / ((n!)"в степени 1/2") < eps. На экран вывести номер задачи и таблицу, содержащую значения F(x) при х, изменяющихся в диапазоне |x| <= 0.7 с шагом 0.1. Таблица должна состоять из 15 строк и 8 столбцов с соответсвующими значениями N, x, F(x), n, вычисленными при различных Eps(0.01, 0.0001, 0.00001). Формула F(x) см. прил. файл.
Код:
program F_12;
uses
	crt;
var
	x : real;
	F : real;
	n : integer;
{================================================}
{функция для расчета факториала}
function fact( y : integer) : longint;
var
	i : integer;
	P : longint;
begin
	if(y <> 0) then
	begin
		P := 1;
		for i := 1 to y do
		begin
			P := P * i;
		end;
		fact := P;
	end
	else
	begin
		fact := 1;
	end;
end;
{================================================}
procedure raschet( eps : real);
var
	number : integer;
begin
	number := 0;
	x := -0.7;
	F := 1;
	writeln('================================================');
	writeln(' N    ', '     x     ', '      F(x)      ', 'n ', '        eps        ');
	writeln('================================================');
	while(x < 0.8) do
	begin
		n := 1;
		F := 1;
		inc(number);

		while(abs(x) / sqrt(fact(n)) >= eps ) do
		begin
			F := F * (1 - abs(x) / sqrt(fact(n)));
			inc(n);
		end;

		writeln(number:2, '      ', x:6:2, '       ',  F:7:6, '    ', n:2, '      ', eps:5:4);
		x := x + 0.1;
	end;
end;
{================================================}
begin
	{при eps = 0.00001 получается слишком большое число, даже longint недостаточно}
	clrscr;
	raschet(0.01);
	raschet(0.001);
	raschet(0.0001);
	writeln('Расчет закончен!!!');

	readln;
end.

у меня просто еще есть одна подобная нерешенная задача, и хочу понять, что делаю не так. Подскажите как быть то?
TakZaglanul
Дата: 15.11.2007 20:03:40
program F_12;
uses
crt;
Компилируешь TurboPascal'ем? И "оно" работает без дополнительных танцев с бубном?
Ну да ладно, это так, лирическое отступление. Теперь по делу. Пока дам идеи, как упростиь код. Во-первых функция Fact здесь только мешает. Используя рекурсивный пересчет множителей, можно обойтись без нее. И зачем лишний раз пересчитывать abs(x) / sqrt(fact(n)) ?
Альт
Дата: 16.11.2007 09:37:44
видимо crt уже после патча таймера... если я правильно помню проблему
S.G.
Дата: 16.11.2007 10:39:29
2 FasterHarder
Вам надо обратить внимание на то, как в циклах можно получать суммы и произведения. Что делает код
while {условие} do S := S + 1/n;
или скажем
while {условие} do 
begin 
  Fact := Fact * n;
  P := P * (1 - x/Fact);
end;

в прошлой задаче вы спотыкались на том же месте.
берете лист бумаги, рисуете (не принтером, а ручкой) табличку, в которой расписываете какие значения получаются в переменных при каждом прохождении цикла. Помогает.
FasterHarder
Дата: 16.11.2007 21:02:32
I started in 1983, in 2007 i still on a case!

автор
Компилируешь TurboPascal'ем? И "оно" работает без дополнительных танцев с бубном?

нет, без бубна не компилиться.

новый вариант таков:
program F_12;
uses
	crt;
var
	x : real;	{передаваемый аргумент}
	F : real;	{значение функции}
	n : integer;	{количество итераций}
	number : byte;	{номер итерации}
{================================================}
function raschet( eps : real) : real;
var
	a : real;	{записываем значение факториала}
	i : integer;	{счетчик}
	P : real;
begin
	P := 1;
	n := 1;
	a := 1;

	while(abs(x) / sqrt(a) >= eps ) do
	begin
		P := P * (1 - abs(x) / sqrt(a));
		inc(n);
		for i := 1 to n do
		begin
			a := a * i;
		end;
	end;

	raschet := P;

end;
{================================================}
begin
	clrscr;
	number := 1;
	x := -0.7;

	writeln('Задача номер A19.1.; процедура F12 ');
	writeln('==============================================================================');
	writeln('  Eps             0.01               0.0001            0.00001');
	writeln('   N       x      F(x)       n        F(x)       n       F(x)       n   ');
	writeln('==============================================================================');

	while(x < 0.8) do
	begin
		F := raschet(0.01);
		write(number:4, '   ', x:6:1, '  ', F:9:5, '   ', n:3 );

		F := raschet(0.0001);
		write(F:14:6, ' ', n:5);

		F := raschet(0.00001);
		writeln(F:14:6, n:5);

		inc(number);
		x := x + 0.1;
	end;
	writeln('==============================================================================');
	writeln('Расчет закончен!!!');

	readln;
end.
TakZaglanul
Дата: 18.11.2007 16:15:41
Не, опять неправильно. Проблема в том, что ты рашаешь задачу "в лоб". Факториал написан - значит и будем его считать. А можно обойтись вообще без подсчета факториала. Обрати внимание, как у тебя меняется выражение
Номер итерациивыражение под знаком П
1 1-abs(x)/1
2 1-abs(x)/(1*sqrt(2))
3 1-abs(x)/(1*sqrt(2)*sqrt(3))

Намного продуктивнее будет что-то типа такого
p:=1 //собственно произведение
a:=abs(x); //выражение, которое будем пересчитывать при каждой итерации
               //обрати внимание, что оно же является критерием завершения обработки
n:=1;  //счетчик итераций
while a>=eps do
 p:=p*(1-a);
 n:=n+1;
 a:=a/sqrt(n)
end;