skilk Posted May 8, 2005 Report Share Posted May 8, 2005 (edited) Вычислить значение суммы членов бесконечного ряда S=-x+((x*x*x)/3)-...+((-1)*n)*(((x)*2n-1)/2n-1)+... с заданной точностью e=0.5*((10)*-4) На печать вывести значение суммы и число членов ряда, вошедших в сумму. ----------------- ОТ МОДЕРАТОРА: Называй темы в соответствии с правилами! Еще одно нарушение и ты повесишь на меня работу просматривать твои сообщения перед их публикацией. Edited May 8, 2005 by Сергей Плоткин Quote Link to comment Share on other sites More sharing options...
Grimm Posted May 8, 2005 Report Share Posted May 8, 2005 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 а меньше дипазон Quote Link to comment Share on other sites More sharing options...
skilk Posted May 9, 2005 Author Report Share Posted May 9, 2005 А на TurboPascale или на delphi как выглядеть будет... Quote Link to comment Share on other sites More sharing options...
Тролль Posted May 9, 2005 Report Share Posted May 9, 2005 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. Quote Link to comment Share on other sites More sharing options...
skilk Posted May 10, 2005 Author Report Share Posted May 10, 2005 Тогда извеняюсь за описку(сомневался что степень так пишется). Тогда надо с точностью e=0.5*10^-4 Quote Link to comment Share on other sites More sharing options...
Тролль Posted May 10, 2005 Report Share Posted May 10, 2005 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. Видишь, написать гораздо легче, чем описать :) Quote Link to comment Share on other sites More sharing options...
skilk Posted May 11, 2005 Author Report Share Posted May 11, 2005 ;) Большое СПАСИБО!!! Quote Link to comment Share on other sites More sharing options...
skilk Posted May 11, 2005 Author Report Share Posted May 11, 2005 ;) Чё то не получается? Дело втом, что я текст набрал, когда компилировать начинаю, то курсор на строку Readln(x); между ") и ;" выводит, и ругается. Говорит следующие Error 116: Must be in 8087 mode to compile this. Пишу в Turbo Pascale Ver. 7.1 Quote Link to comment Share on other sites More sharing options...
Тролль Posted May 11, 2005 Report Share Posted May 11, 2005 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. Quote Link to comment Share on other sites More sharing options...
aleksvander Posted March 29, 2006 Report Share Posted March 29, 2006 Помогите решить пару задачек на Паскале ;) 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)! + ...; Quote Link to comment Share on other sites More sharing options...
Тролль Posted March 30, 2006 Report Share Posted March 30, 2006 (edited) 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 March 30, 2006 by Тролль Quote Link to comment Share on other sites More sharing options...
Romiras Posted March 30, 2006 Report Share Posted March 30, 2006 Советую почитать Вычисление пределов с помощью ряда Тейлора Quote Link to comment Share on other sites More sharing options...
Тролль Posted March 30, 2006 Report Share Posted March 30, 2006 Romiras: Посмотрел это руководство. Прости: ужасно! :D Все достигается лобовой атакой, не считаясь с потерями. Готовую функцию возведения в степень автор программы использовать не хочет, а сам реализует ее кошмарно (на форуме разбиралось, как ее эффективно реализовать). Хотя на самом деле ее вообще использовать не надо. Кроме чистой математики, существует и вычислительная математика. Совершенно ни к чему каждый член ряда вычислять каждый раз полностью заново, надо пользоваться рекуррентными соотношениями (каждый следующий член ряда легко вычисляется через предыдущий). Quote Link to comment Share on other sites More sharing options...
Romiras Posted March 30, 2006 Report Share Posted March 30, 2006 Для начинающих самое то, по-моему. А что такое "готовая" функция возведения в степень? Я такой в Паскале не помню... :D А та реализация степени проста, как раз, как 5 копеек. Есть другие варианты? Насчёт рекуррентности согласен на 100%, но там просто принцип объясняется. Я статью дополню тогда. Вся фишка в том, что нужно только подставить формулу, и больше ничего не нужно. Quote Link to comment Share on other sites More sharing options...
Тролль Posted March 30, 2006 Report Share Posted March 30, 2006 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 ввела. Но увы, чего нет, того нет. Каюсь и посыпаю себе голову пеплом . В Pascal для возведения в степень используется выражение exp(n*ln(x)), уже писал когда-то об этом. Без всяких циклов. Quote Link to comment Share on other sites More sharing options...
can4ec Posted April 15, 2006 Report Share Posted April 15, 2006 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 написан тподскажи? Quote Link to comment Share on other sites More sharing options...
Тролль Posted April 15, 2006 Report Share Posted April 15, 2006 (edited) 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 April 15, 2006 by Тролль Quote Link to comment Share on other sites More sharing options...
can4ec Posted April 15, 2006 Report Share Posted April 15, 2006 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);; } Quote Link to comment Share on other sites More sharing options...
Тролль Posted April 15, 2006 Report Share Posted April 15, 2006 can4ec: Вообще-то на синтаксические ошибки должен указывать сам C++ Builder, у меня он не установлен, поэтому я за него: s=p=-x - нет точки с запятой в конце. p=(-1)^n*x^(2*n-1)/(2*n-1); } - в C++ нет операции возведения в степень, операция ^ в нем имеет другой смысл, а для возведения в степень используется функция pow. И тоже нет точки с запятой в конце оператора. Edit1->Text=IntToStr(s);; - IntToStr умеет преобразовывать целые, а что она преобразует тут? Хотя синтаксической ошибки тут нет. Самое опасное - когда программа работает, но делает не то, что от нее хотят. Ну и лишняя точка с запятой, хотя она тут ни на что не повлияет. Quote Link to comment Share on other sites More sharing options...
can4ec Posted April 16, 2006 Report Share Posted April 16, 2006 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 Почему не отрицательное получается третье число? Quote Link to comment Share on other sites More sharing options...
can4ec Posted April 16, 2006 Report Share Posted April 16, 2006 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)? Quote Link to comment Share on other sites More sharing options...
Тролль Posted April 16, 2006 Report Share Posted April 16, 2006 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) было бы неправильно - сама сумма ряда может быть и довольно большой, а вот точность определения этой суммы равна именно очередному члену ряда. А вообще зачем тебе начинать с вычислительной математики? Это же в первую очередь математика, и только потом программирование. Надо программировать то, что тебе понятно, и ты это объясняешь компьютеру. Например, программа для определения оптимального веса человека по его росту проще и интереснее. Или определение знака зодиака по дате рождения... Или расчет биоритмов... Да мало ли простых и полезных программ с понятной простому человеку тематикой можно придумать... Если тебе самому что-то не совсем понятно, компьютеру это будет непонятно вдвойне - он никогда не додумает за тебя, а, наоборот, воспользуется любой возможностью неправильно истолковать вроде бы понятные тебе вещи. Программирование очень похоже на объяснение, чего ты хочешь, марсианину. Все, что можно, будет понято не так. Quote Link to comment Share on other sites More sharing options...
Eliar Posted November 20, 2021 Report Share Posted November 20, 2021 вычислить сумму бесконечного ряда с погрешностью 0.001. s =x-x/2+x/3-+x/4 ...+(-1)x/n+.... при x=0.1, 0.3 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.