Перейти к содержанию
СофтФорум - всё о компьютерах и не только

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


Рекомендуемые сообщения

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

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

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

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

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

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

Изменено пользователем Сергей Плоткин
Ссылка на комментарий
Поделиться на другие сайты

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 а меньше дипазон

Ссылка на комментарий
Поделиться на другие сайты

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.

Ссылка на комментарий
Поделиться на другие сайты

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

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

Ссылка на комментарий
Поделиться на другие сайты

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. Видишь, написать гораздо легче, чем описать :)

Ссылка на комментарий
Поделиться на другие сайты

;)

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

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

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

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

Пишу в Turbo Pascale Ver. 7.1

Ссылка на комментарий
Поделиться на другие сайты

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.

Ссылка на комментарий
Поделиться на другие сайты

  • 10 месяцев спустя...

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

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)! + ...;

Ссылка на комментарий
Поделиться на другие сайты

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.

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Romiras:

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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)), уже писал когда-то об этом. Без всяких циклов.

Ссылка на комментарий
Поделиться на другие сайты

  • 3 недели спустя...

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 написан тподскажи?

Ссылка на комментарий
Поделиться на другие сайты

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, их оформление - "по вкусу".

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

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);;

}

Ссылка на комментарий
Поделиться на другие сайты

can4ec:

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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 Почему не отрицательное получается третье число?

Ссылка на комментарий
Поделиться на другие сайты

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)?

Ссылка на комментарий
Поделиться на другие сайты

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) было бы неправильно - сама сумма ряда может быть и довольно большой, а вот точность определения этой суммы равна именно очередному члену ряда.

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

  • 15 лет спустя...

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...