Jump to content
СофтФорум - всё о компьютерах и не только

Вычисление значения суммы членов бесконечного ряда


Recommended Posts

Вычислить значение суммы членов бесконечного ряда

S=-x+((x*x*x)/3)-...+((-1)*n)*(((x)*2n-1)/2n-1)+...

с заданной точностью e=0.5*((10)*-4) На печать вывести значение суммы и число членов ряда, вошедших в сумму.

-----------------

ОТ МОДЕРАТОРА:

mod.gif Называй темы в соответствии с правилами! Еще одно нарушение и ты повесишь на меня работу просматривать твои сообщения перед их публикацией.

Edited by Сергей Плоткин
Link to comment
Share on other sites

int N,j,i=0;

long double ep=0.001,Summ=0,an=0;

cout<<endl;

i++;

an=(((3*i)-2)*((3*i)+1));

if (an!=0) {an=(1/an); Summ=Summ+an;}

while (an>=ep)

{

i++;

an=(((3*i)-2)*((3*i)+1));

if (an!=0) {an=(1/an); Summ=Summ+an;}

}

cout<<"Dlya to4nosti 0,001 summa ryada ravna: "<<Summ<<endl;

cout<<"Vsego : "<<i<<" 4lenov"<<endl;

cout<<"Posledniy 4len raven: "<<an<<endl;

функция не твоя и точность не твоя, однако если не совсем из детсада найдешь куда всунуть

[mergetime]1115584776[/mergetime]

да, кстаи ето на турбо сях, если что

[mergetime]1115584931[/mergetime]

и переменные N и i там не нужны, и может можно не long double а меньше дипазон

Link to comment
Share on other sites

skilk:

Мне кажется, у тебя ошибка в записи условия. В формуле первые члены ряда не соответствуют общему выражению для члена ряда.

Возможно, ряд должен выглядеть так?:

S=-x+x^3/3-...+(-1)^n*x^(2*n-1)/(2*n-1)

Тут, как принято в программировании, ^ - знак возведения в степень, порядок выполнения операций - как в обычной математике (например, возведения в степень делаются сначала, умножения - потом). Тогда:

PROGRAM Sequence;

VAR n:Integer; x,p,s:Single;

BEGIN

Readln(x);

n:=1; p:=-x; s:=p;

WHILE Abs(p)>.5e-4 DO

BEGIN

n:=n+1;

p:=-p*x*x*(2*n-3)/(2*n-1);

s:=s+p;

END;

Writeln(s,n);

END.

Link to comment
Share on other sites

Тогда извеняюсь за описку(сомневался что степень так пишется).

Тогда надо с точностью e=0.5*10^-4

Link to comment
Share on other sites

skilk:

Я так и сделал. Три замечания:

а) в Pascal нет операции возведения в степень. Вместо этого есть специальная функция возведения в степень. Мне она тут не понадобилась, я получал каждый следующий член ряда из предыдущего простым умножением. Вообще-то в Pascal, так как в нем нет операции возведения в степень, знак ^ используется для другой цели. Но когда записывают формулу или задачу для себя, а не для компьютера, программисты часто используют не какой-то конкретный язык, а некоторую смесь языков, которая всем понятна. В этом смысле я и использовал обозначения в записи формулы для ряда в начале поста. Получилось в стиле Бейсика.

б) 0.5*10^-4 - это запись не числа, а формулы: возвести 10 в степень -4 и умножить на это 0.5. Как я написал, такая запись формулы в стиле Бейсика, в Pascal вместо возведения степень надо было бы написать вызов функции возведения в степень, но в любом случае при такой записи будут проводиться все эти вычисления. А вот запись .5e-4 (или, что то же, 0.5e-4) - это запись не формулы, а именно числа, то же самое, что написать 0.00005, кстати, такая запись применяется во всех языках программирования, и программа тут считать ничего не будет, а сразу использует это число. Конечно, при счете по формуле получилось бы это же число, но тут компьютеру пришлось бы считать, а возведение в степень - нелегкая операция даже для компьютера (в его масштабах скорости, конечно).

в) я исходил из того, что в условии имеется в виду абсолютная точность (чаще используют слово ошибка). Бывает еще относительная. Абсолютная - это если результат отличается от точного не больше чем на эти .5e-4. Бывает еще относительная ошибка - если результат отличается от точного не на число .5e-4, а на .5e-4 часть от точного результата. Какой именно вид у тебя задан, не написано, но обычно, если не указывают вид точности, имеется в виду абсолютная.

P.S. Видишь, написать гораздо легче, чем описать :)

Link to comment
Share on other sites

;)

Чё то не получается?

Дело втом, что я текст набрал, когда компилировать начинаю, то курсор

на строку Readln(x); между ") и ;" выводит, и ругается.

Говорит следующие Error 116: Must be in 8087 mode to compile this.

Пишу в Turbo Pascale Ver. 7.1

Link to comment
Share on other sites

skilk:

Все ясно. Чтобы использовать тип Single, компилятор должен работать в режиме допустимости использования аппаратной поддержки вычислений с плавающей запятой, то есть в Options - Compiler - Numeric processing должно быть установлено значение 8087/80287. Но можно ничего в настройках Турбопаскаля не менять и использовать режим, в котором компилятор работает по умолчанию, тогда надо во второй строке программы Single заменить на Real. Так и советую сделать.

Дальше, 0 в записи 0.5e-4 все-таки оказался необходимым, добавь его. Наследство того, что Паскаль создавал не американец.

После этого все будет работать. Но чтобы удобнее было читать результаты, замени еще Writeln(s,n); на Writeln('s=',s,' n=',n);

После запуска программы никакая подсказка на ввод значения x не выдается, программа просто ждет ввода значения x, мигая текстовым курсором. Значение надо вводить в виде 0.8 или 0.4 или, если хочешь, 5e-1, всегда завершая ввод нажатием клавиши Enter. Но помни, что вводимое значение должно быть меньше 1, иначе ряд не имеет конечной суммы и программа выдаст ошибку. При желании можешь внести в программу вывод подсказки для ввода, например, введи оператор Writeln('Введите x'); перед оператором Readln(x);

Кроме того, сразу после вывода результата ты автоматически возвращаешься в экран с текстом программы. Это нормально, но чтобы не быть обескураженным, когда после ввода значения x сразу появится экран с текстом программы, надо знать, что чтобы увидеть экран ввода-вывода, надо нажать Alt+F5, а повторным нажатием возвращаешься снова в экран с текстом программы. Для отладки можно сделать немного удобнее, вставив после оператора вывода Writeln('s=',s,' n=',n); еще строку с оператором Readln; Тогда программа после вывода результата не сразу переключится на экран с текстом программы, а будет ждать нажатия клавиши Enter.

Link to comment
Share on other sites

  • 10 months later...

Помогите решить пару задачек на Паскале ;)

S=7x + 7x^3/3 + 7x^5/5 + ... + 7x^(2n+1)/(2n+1)

и

Вычислить бесконечную сумму с заданной точностью eps (eps>0). Считать, что точность достигнута, если очередное слагаемое по модулю меньше eps, - все последующие слагаемые можно уже не учитывать.

S=x + (x^3)/3! + (x^5)/5! + ... + (x^(2n+1))/(2n+1)! + ...;

Link to comment
Share on other sites

aleksvander:

Так почти то же, с чего топик начинался. Только слегка подкорректировать соответственно изменившимся условиям.

Первая задачка:

var eps,S,T,X,X2,P:Real;

begin

Write('eps: '); ReadLn(eps);

Write('x: '); ReadLn(X);

T:=7*X; S:=T; X2:=X*X; P:=1;

while Abs(T)>=eps do

begin

T:=T*X2*P; P:=P+2; T:=T/P; S:=S+T;

end;

WriteLn('S=',S);

end.

Вторая задачка:

var eps,S,T,X,X2,P:Real;

begin

Write('eps: '); ReadLn(eps);

Write('x: '); ReadLn(X);

T:=X; S:=T; X2:=X*X; P:=1;

while T>eps do

begin

T:=T*X2/(P+1)/(P+2); P:=P+2; S:=S+T;

end;

WriteLn('S=',S);

end.

Edited by Тролль
Link to comment
Share on other sites

Romiras:

Посмотрел это руководство. Прости: ужасно! :D

Все достигается лобовой атакой, не считаясь с потерями. Готовую функцию возведения в степень автор программы использовать не хочет, а сам реализует ее кошмарно (на форуме разбиралось, как ее эффективно реализовать). Хотя на самом деле ее вообще использовать не надо. Кроме чистой математики, существует и вычислительная математика. Совершенно ни к чему каждый член ряда вычислять каждый раз полностью заново, надо пользоваться рекуррентными соотношениями (каждый следующий член ряда легко вычисляется через предыдущий).

Link to comment
Share on other sites

Для начинающих самое то, по-моему.

А что такое "готовая" функция возведения в степень? Я такой в Паскале не помню... :D А та реализация степени проста, как раз, как 5 копеек. Есть другие варианты?

Насчёт рекуррентности согласен на 100%, но там просто принцип объясняется. Я статью дополню тогда.

Вся фишка в том, что нужно только подставить формулу, и больше ничего не нужно.

Link to comment
Share on other sites

Romiras:

А, это твоя статья? ИМХО, действительно лучше дополнить, уж очень неэффективно вычисление рядов "в лоб".

Чтобы получить формулу для рекуррентного вычисления членов ряда, просто делим запись одного члена ряда на запись предыдущего члена ряда. Например, для синуса (x^i/i!) / ((x^(i-2)/(i-2)!) = x^2/(i*(i-1)) , так что новый член ряда каждый раз получается просто умножением старого на это выражение, без всяких факториалов и степеней (тут значения i меняется при переходе к следующему члену ряда каждый раз на 2).

На самом деле это формальное доказательство, человеку проще использовать словесное описание: при переходе от(x^3/3!) к (x^5/5!) степень увеличивается на два, то есть надо множить на x^2, а знаменатель увеличивается в 5!/3! раз, то есть в 4*5. Аналогично будет и в будущем. Множить всегда придется на икс квадрат, а делить надо сначала на 4*5, потом на 6*7, потом на 8*9 и т.д., это легко запрограммировать.

А вот функции возведения в степень в Turbo Pascal действительно нет, тут я перепутал Turbo Pascal с Turbo C, там такая функция называется Pow. Мне почему-то казалось, что Borland ее и в Turbo Pascal ввела. Но увы, чего нет, того нет. Каюсь и посыпаю себе голову пеплом :blink: . В Pascal для возведения в степень используется выражение exp(n*ln(x)), уже писал когда-то об этом. Без всяких циклов.

Link to comment
Share on other sites

  • 3 weeks later...

skilk:

Мне кажется, у тебя ошибка в записи условия. В формуле первые члены ряда не соответствуют общему выражению для члена ряда.

Возможно, ряд должен выглядеть так?:

S=-x+x^3/3-...+(-1)^n*x^(2*n-1)/(2*n-1)

Тут, как принято в программировании, ^ - знак возведения в степень, порядок выполнения операций - как в обычной математике (например, возведения в степень делаются сначала, умножения - потом). Тогда:

PROGRAM Sequence;

VAR n:Integer; x,p,s:Single;

BEGIN

Readln(x);

n:=1; p:=-x; s:=p;

WHILE Abs(p)>.5e-4 DO

BEGIN

n:=n+1;

p:=-p*x*x*(2*n-3)/(2*n-1);

s:=s+p;

END;

Writeln(s,n);

END.

А как этот пример будет на с++Builder написан тподскажи?

Link to comment
Share on other sites

can4ec:

Вот и попробовал бы написать сам, а если что-то не получилось бы, выложил сюда. Очень полезно переводить программы с одного языка на другой.

Вычислительная часть, после объявления переменных

int n; float x,p,s;

может выглядеть почти как на Pascal:

n=1; p=-x; s=p; while (abs(p)>.5e-4) {n=n+1; p=-p*x*x*(2*n-3)/(2*n-1); s=s+p;};

Или, "в стиле C", все вычисления можно записать одним оператором:

for(n=2,s=p=-x; abs(p)>.5e-4; n++,s+=p) p*=-x*x*(2*n-3)/(2*n-1);

P.S. И, конечно, не забыть ввод значения x и вывод значений s и n, их оформление - "по вкусу".

Edited by Тролль
Link to comment
Share on other sites

can4ec:

Вот и попробовал бы написать сам, а если что-то не получилось бы, выложил сюда. Очень полезно переводить программы с одного языка на другой.

Вычислительная часть, после объявления переменных

int n; float x,p,s;

может выглядеть почти как на Pascal:

n=1; p=-x; s=p; while (abs(p)>.5e-4) {n=n+1; p=-p*x*x*(2*n-3)/(2*n-1); s=s+p;};

Или, "в стиле C", все вычисления можно записать одним оператором:

for(n=2,s=p=-x; abs(p)>.5e-4; n++,s+=p) p*=-x*x*(2*n-3)/(2*n-1);

P.S. И, конечно, не забыть ввод значения x и вывод значений s и n, их оформление - "по вкусу".

Ну вот я попробовал на Builder только че-то не пашет:

{

int x=2;

float p;

int n;

float s;

s=p=-x

for(n=2;abs(p)>0.001;n++,s+=p) {

p=(-1)^n*x^(2*n-1)/(2*n-1); }

Edit1->Text=IntToStr(s);;

}

Link to comment
Share on other sites

can4ec:

Вообще-то на синтаксические ошибки должен указывать сам C++ Builder, у меня он не установлен, поэтому я за него:

s=p=-x - нет точки с запятой в конце.

p=(-1)^n*x^(2*n-1)/(2*n-1); } - в C++ нет операции возведения в степень, операция ^ в нем имеет другой смысл, а для возведения в степень используется функция pow. И тоже нет точки с запятой в конце оператора.

Edit1->Text=IntToStr(s);; - IntToStr умеет преобразовывать целые, а что она преобразует тут? Хотя синтаксической ошибки тут нет. Самое опасное - когда программа работает, но делает не то, что от нее хотят. Ну и лишняя точка с запятой, хотя она тут ни на что не повлияет.

Link to comment
Share on other sites

can4ec:

Вообще-то на синтаксические ошибки должен указывать сам C++ Builder, у меня он не установлен, поэтому я за него:

s=p=-x - нет точки с запятой в конце.

p=(-1)^n*x^(2*n-1)/(2*n-1); } - в C++ нет операции возведения в степень, операция ^ в нем имеет другой смысл, а для возведения в степень используется функция pow. И тоже нет точки с запятой в конце оператора.

Edit1->Text=IntToStr(s);; - IntToStr умеет преобразовывать целые, а что она преобразует тут? Хотя синтаксической ошибки тут нет. Самое опасное - когда программа работает, но делает не то, что от нее хотят. Ну и лишняя точка с запятой, хотя она тут ни на что не повлияет.

Я не могу понять как это ты возводишь в степень. Придставим что

x=1 тогда p=-1 , s=p=-1

n=2 p=1*1*1(2*2-1)/(2*2-1)=1/3;

s=-1+1/3;

Теперь n=3

p=1*1*1(2*3-1)/(2*3-1)=1/5 <---- новедь должно получится -1/5 Почему не отрицательное получается третье число?

Link to comment
Share on other sites

int x=2;

float p;

int n;

float s;

for(n=2,s=-x;abs(s)>0.001;n++) {

p=(pow(-1,n)*pow(x,2*n-1))/(2*n-1);

s+=p; }

Edit1->Text=FloatToStr(s);

Я решил все сделать через pow спасибо. Хотел спросить мне кажется что модель надо брать не от abs(p) а вот так abs(s)?

Link to comment
Share on other sites

can4ec:

Я не могу понять как это ты возводишь в степень.
Я не возвожу в степень вообще. Члены ряда можно вычислять двумя способами: прямым и рекуррентным. Рекуррентный способ не требует возведения в степень. Прочитай то, что я написал Romires'у.

Что такое рекуррентный способ? Например, берем ряд: 1, 2, 4, 8...

Его можно вычислять так: 2º=1, 2¹=2, 2²=4, 2³=8...

А можно иначе: 1, 2*1=2, 2*2=4, 2*4=8...

Второй способ - рекуррентный, как видишь, мы обходимся без возведения в степень.

Я вообще не понимаю, откуда ты взял свою формулу в сообщении, в котором ты просчитываешь пример вручную, это какой-то гибрид между формулами для двух способов.

Кстати, сумму этого ряда можно посчитать еще проще - это всего лишь -arctg(x), но тогда программировать было бы просто нечего...

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

А вообще зачем тебе начинать с вычислительной математики? Это же в первую очередь математика, и только потом программирование. Надо программировать то, что тебе понятно, и ты это объясняешь компьютеру.

Например, программа для определения оптимального веса человека по его росту проще и интереснее. Или определение знака зодиака по дате рождения... Или расчет биоритмов... Да мало ли простых и полезных программ с понятной простому человеку тематикой можно придумать...

Если тебе самому что-то не совсем понятно, компьютеру это будет непонятно вдвойне - он никогда не додумает за тебя, а, наоборот, воспользуется любой возможностью неправильно истолковать вроде бы понятные тебе вещи. Программирование очень похоже на объяснение, чего ты хочешь, марсианину. Все, что можно, будет понято не так.

Link to comment
Share on other sites

  • 15 years later...

вычислить сумму бесконечного ряда с погрешностью 0.001.
s =x-x/2+x/3-+x/4 ...+(-1)x/n+.... при x=0.1, 0.3

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...