Помощь - Поиск - Пользователи - Календарь
Полная версия: Приближененное вычисление значения ряда
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Account
Задание
Изображение
Мой код

uses crt;
var
zn:boolean;
s,x,st,e:double;
p_st,i,j,c:longint;
begin
clrscr;
s:=1;
zn:=false;
e:=0.1;
x:=0.9;
i:=1;
j:=2;
p_st:=1;
st:=1;
while (abs(x)<1) and (abs(1/sqrt(1+x)-s)>e) do
begin
x:=x-0.1;
for c:=1 to p_st do
st:=st*x;
if zn=false then
begin
s:=s-(i*st/j);
zn:=true;
end
else
begin
s:=s+(i*st/j);
zn:=false;
end;
j:=(i+3)*j;
i:=(i+2)*i;
{------------------------------------------}
writeln('e= ',e:5:5);
writeln('i= ',i);
writeln('j= ',j);
writeln('x= ',x:5:5);
writeln('s= ',s:5:5);
writeln('(1/sqrt(1+x))= ',(1/sqrt(1+x)):5:5);
writeln('(1/sqrt(1+x)-s)= ',abs(1/sqrt(1+x)-s):5:5);
end;
writeln('i= ',i);
writeln('j= ',j);
writeln('e= ',e:5:5);
writeln('x= ',x:5:5);
writeln('s= ',s:5:5);
writeln('(1/sqrt(1+x))= ',(1/sqrt(1+x)):5:5);
writeln('(1/sqrt(1+x)-s)= ',abs(1/sqrt(1+x)-s):5:5);
readkey;
end.

Вот с точностью 0,1 он вычисляет, если сменить поставить точность выше, при этом соответсвенно и шаг нужно уменьшить допусти 0,01 сделать его, то все программа не пашет, я так понялне хватает размераности типов данных, переменная j обнуляется, а еще заметил i выходит за пределы и становится равной -1. Правильные ли у меня вычисления и как сделать чтоб вычислить с более высокой точностью?
volvo
Цитата
как сделать чтоб вычислить с более высокой точностью?
Не надо постоянно вычислять Xn, просто домножай очередной член ряда на X:
var next: double;
...
e := 0.1; { <--- замени на 0.0001 и получишь гораздо более точную сумму }
s := 1; next := 1;
i := 1;
x := 0.9;
repeat
next := -next * i * x / succ(i);
s := s + next; inc(i, 2);
until abs(next) <= e;
writeln('e = ', e:10:6, 's = ', s:10:6);

Account
При замени уже на 0,01 вылетает ошибка операции с плавующей точкой(
volvo
Цитата
При замени уже на 0,01 вылетает ошибка операции с плавующей точкой(
Интересное кино... У меня прекрасно работает при e = 0.00001:
Нажмите для просмотра прикрепленного файла

Account
volvo, а как у тебя знак последующего множителя в ряде определяется не пойму?

Все понял, звиняй за тупой вопрос))
Account
volvo, огромное спасибо, очередной раз убеждаюсь что ты просто гений))) good.gif
По твоему примеру решаю и другие подобные задачи))))

Добавлено через 8 мин.
volvo, а вот только не пойму у тебя ведь переменная x не меняется? а для нее ведь тоже указана область значание?
Account
Задача таже только другой ряд
Изображение
Вот код, сделанный на основе предложенного
выше vovlo
uses crt;
var
s,x,e:double;
i:longint;
next:double;
begin
clrscr;
write('Введите значение e (точности)= '); {0.001}
readln(e);
x:=0.9;
s:=x;
next:=x;
i:=3;
next:= next*sqr(x)/i;
s:=s-next;
repeat
next:= next*sqr(x)/i;
s:=s+next; inc(i,2);
x:=x-e;
writeln('x= ',x:5:7);
writeln('s= ',s:5:7);
writeln('arctan(x)= ',arctan(x):5:7);
until abs(s-arctan(x))<e;
writeln('e= ',e:5:7);
writeln('x= ',x:5:7);
writeln('s= ',s:5:7);
writeln('arctan(x)= ',arctan(x):5:7);
writeln('s-arctan(x)= ',abs(s-arctan(x)):5:7);
readkey;
end.

Работае, толко вот при постановке точности (сравнивается значение введенной точности с разницей между сумой членов ряда и арктангенсом) в 0,001 он пролетает, ранее найденные значения при меньшей точности. x уходит соотвественно в минус и арктангенс тоже а сумма ряда то нет, как повысить опять же точность?
volvo
Цитата
а вот только не пойму у тебя ведь переменная x не меняется? а для нее ведь тоже указана область значание?
А что, где-то указано, что она должна меняться? Переменная попадает в допустимый интервал, |0.9| < 1, для этого значения и вычисляется ряд...

Цитата
Вот код, сделанный на основе предложенного выше
Ни разу не по моему методу smile.gif
Вот тут я выкладывал реализацию arctan: Вычисление значений тригонометрических функций на основе разложения в ряд Маклорена , соответственно по моему методу вычисление будет вот таким:

  x := 0.9;
s := 0; next := x; i := 1;
repeat
s := s + next / i;
next := - next * sqr(x);
inc(i, 2);
until abs(next) < e;
У тебя опять та же ошибка: во время вычисления суммы ряда X не должно меняться, ты же вычисляешь arctan(X), а не arctan(X - delta .. X + delta)... Если тебе надо вычислить ряд для нескольких разных значений X, то оберни это еще одним циклом, в котором меняй аргумент. Но во время самого вычисления суммы ряда значение X для тебя должно оставаться неприкосновенным.
Account
Вот шапка задания из таблицы
Изображение
отсюда я и изменяю аргумет x. Метод я имел ввиду по вычислению ряда а не арктангенса smile.gif , взял принцип, но заменил вычисление условие точности и сам вычисляемый ряд)))
Я думал что x тоже должна менятся( поэтому так и сделал, буду править)
Account
volvo
Вот сделал для каждого x

uses crt;
var
s,x,e:double;
i:longint;
next:double;
begin
clrscr;
write('Введите e = '); {0.001}
readln(e);
x:=0.9;
while abs(x)<1 do
begin
s:=x;
next:=x;
i:=3;
next:= next*sqr(x)/i;
s:=s-next;

repeat
next:= next*sqr(x)/i;
s:=s+next; inc(i,2);
until abs(next)<e;
write('e= ',e:5:5);
write('| x= ',x:5:2);
write('| s= ',s:5:7);
write('| arctan(x)= ',arctan(x):5:7);
writeln;
x:=x-0.1;
end;
readkey;
end.


В условии по while стоит abs(x)<1 а он всеравно захватывает x=-1, почему? (странно при этом значении должно ведь выходить из цикла)

Пришлось сделать через постусловие и поставить 0,9 границу.
volvo
Цитата
В условии по while стоит abs(x)<1 а он всеравно захватывает x=-1, почему?
А ты отладчиком пробегись, и посмотри, чему в действительности равен Х... У меня на последней итерации отладчик показывает
x = -0.99999999999999967
, а при выводе значение округляется до -1. То есть, фактически все верно, модуль значения меньше 1, и цикл продолжается. Чтобы поправить:
while abs(x) < (1.0 - e / 10) do begin
...


Да, кстати. Проверь задание. Ты сравниваешь результаты вычисления суммы ряда с ArcTan, а вычисляется совсем не арктангенс. У арктангенса ряд - знакопеременный, чередуются +/-/+/-, а у тебя только первый минус, потом все плюсы. Поэтому такая большая разность и выходит...
Account
За поправку спасибо.
Цитата
Да, кстати. Проверь задание. Ты сравниваешь результаты вычисления суммы ряда с ArcTan, а вычисляется совсем не арктангенс. У арктангенса ряд - знакопеременный, чередуются +/-/+/-, а у тебя только первый минус, потом все плюсы. Поэтому такая большая разность и выходит...


Возьму на заметку, хорошо что ты заметил, но понимаешь задание только на картинке, больше узнать не где, там вот не указана переменность знака поэтому так вычисляю. Делаю тоже не для себя. (Берусь так сказать помочь знакомым, чтоб вещество серое не засохло;).

p.s. Попробовал знак сделать переменным, действительно значение стало более близкое к арктангенсу) (но сравнивая, вроде не настолько уж большая))) разница)

Добавлено через 19 мин.
volvo
А вот в первом случае , в котором ты решение давал в самом начале разница очень большая между суммой ряда и значением с сравниваемой фунции, вот код

uses crt;
var
s,x,e:double;
i:longint;
next:double;
begin
clrscr;
write('Введмите е = ');
readln(e);
s:=1;
next:=1;
i:=1;
x:=0.9;
while abs(x)<(1.0-e/10) do
begin
repeat
next:= -next*i*x/succ(i);
s:=s+next; inc(i,2);
until abs(next)<e;
write('e= ',e:5:5);
write('| x= ',x:5:2);
write('| s= ',s:5:6);
write('| 1/sqrt(1+x)= ',(1/sqrt(1+x)):5:6);
writeln;
x:=x-0.1;
end;
readkey;
end.

функция значение которой как бы является точным значение ряда (1+x)^(-1/2)
volvo
Перенести
s:=1;
next:=1;
i:=1;

внутрь цикла While не пробовал? У тебя получается накопленная сумма какая-то.
Account
Блин даже стыдно за невнимательность)

Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.