Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите решить задачу C++

82K
21 мая 2012 года
sayuri
4 / / 21.05.2012
Пожалуйста, помогите решить задачку. Долго мучаюсь, никак не могу даже начать. :(

Вычислить и вывести на печать с точностью 0.0001 значение суммы

Попробывала так:
#include <stdio.h>
#include <math.h>
void main()
{
float a=1.,s=1.;
int k=1;
while (fabs(a)>0.0001)
{
a*=1./(2*k+1);
s+=a;
k++;
}
printf ("s=%f",s);
}

Но не уверена в правильности...
83K
21 мая 2012 года
tankograd
3 / / 20.05.2012
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <clocale>
#include <math.h>

int main()
{ int k=1;
double S, t;
float eps=0,0001;
setlocale (LC_CTYPE,"rus");
t=(pow( k,2)/(2*k+1));
S=t;
while (fabs(t)>eps)
{
k=k+1;
t=(pow( k,2)/(2*k+1));
S=S+t;
}
cout<<S<<" Вычисленно с заданной точностью "<<eps<<endl;
return 0 ;
}
2.1K
21 мая 2012 года
disputant
95 / / 28.05.2007
Вы что, люди!
Первое - считать каждый раз очередной член с нуля... Второе - считать с применением pow()... Третье - если считать, то не терять факториал, танкоградная программа просто не завершится :)

Четвертое - вообще-то для повышения точности суммы считаются обычно с меньшего члена к большему, ну да это простим :)


Код:
#include <iostream.h>


int main(int argc, const char * argv[])
{
    double sum = 0.0;
    double term = 1./6.;
    for(int k = 1; term > 0.00001; ++k) // Точность - с запасом!
    {
        sum += term;
        term *= (k+1)/(2.0*k*k*(2*k+3));
    }

    std::cout << sum << std::endl;
}
Примерно так :)
82K
21 мая 2012 года
sayuri
4 / / 21.05.2012
А как это можно преобразовать в Borland C++ for DOS?
а то при вводе выявляются ошибки :(
2.1K
21 мая 2012 года
disputant
95 / / 28.05.2007
Гм, ничего такого 32-разрядного не вижу...
Может, он cout не понимает? Замените
#include <iostream.h>
на
#include <stdio.h>

и
std::cout << sum << std::endl;
на
printf("Sum = %lf\n",sum);

Так работает?

И - если сообщаете об ошибках, не забывайте указывать - какие. Телепатов нет...
82K
21 мая 2012 года
sayuri
4 / / 21.05.2012
ошибка была Parameter argc is never used; Parameter argv is never used
Убрала их из main и получился ответ 0.201786. У вас получился такой же ответ?

а можете это пояснить?
double sum = 0.0;
double term = 1./6.;
2.1K
21 мая 2012 года
disputant
95 / / 28.05.2007
Цитата: sayuri
ошибка была Parameter argc is never used; Parameter argv is never used



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

Цитата: sayuri

Убрала их из main и получился ответ 0.201786. У вас получился такой же ответ?



Нет, это вы точность ухудшили... С моими параметрами (а не 0.0001) получается 0.20183. Дело в том, что все члены ряда - положительны, так что гарантировать, что сумма остатка меньше отброшенного члена нельзя (это для знакопеременных рядов). Потому я и брал точность ПОВЫШЕННУЮ.

Цитата: sayuri
а можете это пояснить?
double sum = 0.0;
double term = 1./6.;



Конечно, могу :) sum - здесь накапливаем сумму, term - текущий член, при k=1 равен 1/6. В цикле я для каждого k считаю член a_{k+1}...
Кстати, лучше переписать так (так самый последний член тоже будет добавлен, и для моего результата хватит даже точности 0.0001):


Код:
#include <iostream.h>


int main(int argc, const char * argv[])
{
    double sum;
    double term;
    sum = term = 1./6.;
    for(int k = 1; term > 0.00001; ++k) // Точность - с запасом!
    {
        term *= (k+1)/(2.0*k*k*(2*k+3));
        sum += term;
    }

    std::cout << sum << std::endl;
}
82K
21 мая 2012 года
sayuri
4 / / 21.05.2012
А так при k=1 разве не 1/3 будет? о_о
252
22 мая 2012 года
koderAlex
1.4K / / 07.09.2005
Код:
#include <stdio.h>

void main(void)
{
long double summ,old,term,a,b;
int i = 1;
term = 1./6. ;
summ = term;
while(1)
  {
  printf("%.18Lf \n",summ);
  i++;
  a = i*i+2.*i+1;
  b = 4.*i*i*i*i+10.*i*i*i+6.*i*i;
  term = term*a/b;
  old = summ;
  summ = summ+term;
  if((summ-old)==0.)break;
  };
printf("%.18Lf",summ);
}
2.1K
22 мая 2012 года
disputant
95 / / 28.05.2007
Цитата: sayuri
А так при k=1 разве не 1/3 будет? о_о



1*1/(2*1+1)! = 1/3! = 1/(1*2*3)=1/6

Где я ошибся?...

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

252
22 мая 2012 года
koderAlex
1.4K / / 07.09.2005
Цитата: disputant
[quote=sayuri;82620]А так при k=1 разве не 1/3 будет? о_о


1*1/(2*1+1)! = 1/3! = 1/(1*2*3)=1/6
Где я ошибся?...
P.S. А вообще, глядя на ответы к этой задаче и встающие новые вопросы, все больше прихожу к решению - все, надо валить из этой темы, а то я и в самом деле начну сомневаться, действительно ли надо ли уметь думать, чтоб программировать... :([/quote]
у мну тоже 1/6 . )
а вот итерационный множитель у вас неверен был .
и точность 0.00001 маловата для быстро сходящегося ряда .

2.1K
22 мая 2012 года
disputant
95 / / 28.05.2007
Цитата: koderAlex

а вот итерационный множитель у вас неверен был .
и точность 0.00001 маловата для быстро сходящегося ряда .



По второму вопросу - в задаче требуется 0.0001, я взял в 10 раз меньше. С учетом факториала для достижения точности 0.0001 вполне достаточно - убедитесь сами.

По первому... Знаете, давайте посчитаем руками для k=2:
2*2/(2*2+1)! =4/(1*2*3*4*5) = 1/30, т.е. 0.03333333...

Вставляем в мою программу вывод членов, и в вашу. Получаем
у меня - 0.03333...
у вас - 0.0089285714...

Так что не хочется вас обижать, но кто бы говорил :)

Еще по первому вопросу о точности. Вот промежуточные результаты:

 
Код:
Term = 0.0333333333,  Sum = 0.2000000000
Term = 0.0017857143,  Sum = 0.2017857143
Term = 0.0000440917,  Sum = 0.2018298060
Term = 0.0000006263,  Sum = 0.2018304323
Term = 0.0000000058,  Sum = 0.2018304381
Как видите, ограничение 0.0001 дает 0.2018298060, мое - 0.00001 - дает 0.2018304323, до 8 знака после запятой.

О сравнительной эффективности наших программ молчу... Мои - 5 умножений, 1 деление, 3 сложения, у вас - 12 умножений, 5 сложений, 1 деление и 1 вычитание (кстати, я понимаю, что вы просто хотите использовать предел точности, но ведь проверка на равенство нулю при плавающей точке - большая некорректность даже в таком ее применении...).

Простите, ужасно не люблю, когда меня тычут носом в ошибки, которых у меня нет - тогда я зверею и тут уж под руку лучше не попадаться :)
2.1K
22 мая 2012 года
disputant
95 / / 28.05.2007
И еще - вот вам решение "в лоб", чтоб снять все сомнения:

Код:
#include <stdio.h>

double fact(int n)
{
    double p = 1.0;
    while(n > 1) p *= n--;
    return p;
}


int main(int argc, const char * argv[])
{
    double sum = 0;
    double term = 1;
    for(int k = 1; term > 0.00000001; ++k) // Точность - с запасом!
    {
        term = k*k/fact(2*k+1);
        sum += term;
        printf("Term = %.10lf,  Sum = %.10lf\n",term,sum);
    }
}
Его результаты:

 
Код:
Term = 0.1666666667,  Sum = 0.1666666667
Term = 0.0333333333,  Sum = 0.2000000000
Term = 0.0017857143,  Sum = 0.2017857143
Term = 0.0000440917,  Sum = 0.2018298060
Term = 0.0000006263,  Sum = 0.2018304323
Term = 0.0000000058,  Sum = 0.2018304381
252
23 мая 2012 года
koderAlex
1.4K / / 07.09.2005
ага , косяк у мну . надо :
a = i*i+2.*i+1;
b = 4.*i*i*i*i+10.*i*i*i+6.*i*i;
i++;
вот что значит на скорую руку писать )
с оптимизацией студень пусть сам справляется .

в каком месте сравнивать с нулём разность некорректно ?
2.1K
23 мая 2012 года
disputant
95 / / 28.05.2007
 
Код:
old = summ;
summ = summ+term;
if((summ-old)==0.)break;
Формально сравнивать число с плавающей точкой на равенство с нулем некорректно. Понятно, что это будет работать практически всегда, и все же, все же... :)
Ну и при таком решении точность-то все равно оказывается конкретно не оценена.
252
24 мая 2012 года
koderAlex
1.4K / / 07.09.2005
в данном случае всё корректно .
при таком решении точность определяется точностью типа данных .
2.1K
24 мая 2012 года
disputant
95 / / 28.05.2007
Цитата: koderAlex
в данном случае всё корректно .
при таком решении точность определяется точностью типа данных .



Вы ее можете конкретно назвать ДЛЯ РЕШЕНИЯ ЗАДАЧИ?
Т.е. ваш ответ - ........., с точностью ..........?
Так сказать, заполните пробелы... Реальные-то задачи решаются не для того, чтоб показать умение программировать, а чтобы решит математическую задачу... Понятно, что данная конкретная задача имеет конкретный ответ - (e^2-3)/(8*e), но представим, что ответ нам заранее неизвестен. Что вы можете сказать о точности своего ответа?

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог