2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 Си, вычисления
Сообщение13.10.2016, 16:04 
Аватара пользователя


10/10/16
22
Дано натуральное n и действительное a. Вычислить:
$\frac1a + \frac1{a(a+1)} + \frac1{a(a+1).....(a+n)}$
Код:
Код:
#include <stdio.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
   int n;
   double a;
   cin >> a;
   cin >> n;
   double result = 0;
   for (int i =0; i < n; i++)
   {
      double temp = a;
      for (int j = 1; j < i; j++)
      {
         temp *= (a + j);
      }
      result += 1 / temp;
   }
   cout << result;
   return 0;
   _getch();
}


Проблема в том, что считает не правильно.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:12 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Подсказка по алгоритму: можно temp не считать каждый раз заново, а взять почти готовый с предыдущего прохода цикла.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:13 
Заслуженный участник


16/02/13
4195
Владивосток
Вы считаете $\frac1a+\frac1a+\frac1{a(a+1)}+\dots+\frac1{a(a+1)\dots(a+n-1)}$, по-моему.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:13 
Заслуженный участник
Аватара пользователя


30/01/06
72407
А так, ошибка в условиях циклов, надо разобраться с нумерацией.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:15 
Заслуженный участник


09/05/12
25179
Если, например, n=3, то цикл вида for (int i =0; i < n; i++) будет выполняться для значений i, равных 0, 1 и 2. Ни на какие мысли это обстоятельство не наводит?

Кстати, код вообще ужасен. Можно, конечно, поправить оба цикла так, чтобы все работало, но еще лучше - от одного из циклов полностью избавиться, он не нужен.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:19 
Аватара пользователя


10/10/16
22
iifat в сообщении #1159444 писал(а):
Вы считаете $\frac1a+\frac1a+\frac1{a(a+1)}+\dots+\frac1{a(a+1)\dots(a+n-1)}$, по-моему.

Даа, результат примерно такой и выдает.
Pphantom в сообщении #1159449 писал(а):
Если, например, n=2, то цикл вида for (int i =0; i < n; i++) будет выполняться для значений i, равных 0, 1 и 2. Ни на какие мысли это обстоятельство не наводит?

Кстати, код вообще ужасен. Можно, конечно, поправить оба цикла так, чтобы все работало, но еще лучше - от одного из циклов полностью избавиться, он не нужен.

Это да. Изучаю Си месяц со странными преподами в универе, поэтому все так.

Munin в сообщении #1159443 писал(а):
Подсказка по алгоритму: можно temp не считать каждый раз заново, а взять почти готовый с предыдущего прохода цикла.

Это да, сейчас попрообую.

-- 13.10.2016, 17:20 --

Pphantom в сообщении #1159449 писал(а):
Если, например, n=2, то цикл вида for (int i =0; i < n; i++) будет выполняться для значений i, равных 0, 1 и 2. Ни на какие мысли это обстоятельство не наводит?

Аааааааааааааа, спасибо. Понял.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:41 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Путаница с индексами циклов - типична для начинающих. Особенно сбивает то, что в стандартной сишной шапке цикла
    for (int index = begin; index < end; ++ index)
индекс принимает значение begin (в первом проходе), но не принимает значение end.

Советы такие:
1) Очень тщательно, аккуратно и на бумажке, выпишите, что означает индекс цикла, и что означают все остальные величины при этом значении индекса. (Например, если вы суммируете $\sum_{i=1}^n,$ а индекс с нуля, то "программистский" индекс будет каждый раз на единичку меньше "математического".)
2) Прогоняйте мысленно циклы при малых числах итераций: 0, 1, 2. Именно это вам и продемонстрировал Pphantom.
3) Аналогично, мысленно прогоняйте первую, последнюю итерации цикла. Иногда вторую и предпоследнюю.

В принципе, пока индексы числовые, можно использовать другую шапку цикла
    for (int index = begin; index <= end; ++ index)
но этого делать не рекомендуется. Это отклонение от сишной традиции. Вы запутаетесь сами, запутаете потенциального читателя вашего кода. И вам труднее будет перейти к более абстрактной идее, реализованной, например, в STL:
    for (iterator iter = begin; iter != end; ++ iter)
которая тоже стандарт, на более высоком уровне.

-- 13.10.2016 16:45:22 --

См. тж. Fencepost error.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:51 
Заслуженный участник


09/05/12
25179
letovpowergameisover в сообщении #1159451 писал(а):
Аааааааааааааа, спасибо. Понял.
Странно. :-) Я там опечатался, имелось в виду n=3. Сейчас в своем сообщении я это исправил.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 17:07 
Аватара пользователя


10/10/16
22
Pphantom в сообщении #1159467 писал(а):
letovpowergameisover в сообщении #1159451 писал(а):
Аааааааааааааа, спасибо. Понял.
Странно. :-) Я там опечатался, имелось в виду n=3. Сейчас в своем сообщении я это исправил.


Да хоть n=10, там ошибка была поонятно в чем)

-- 13.10.2016, 18:07 --

Код:
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <conio.h>
using namespace std;

int main()
{
   int n;
   double a;
   cin >> a;
   cin >> n;
   double temp = a;
   double result = 0;
   for (int i = 0; i < n + 1; i++)
   {
      temp *= a + i;
      result += 1 / temp;
   }
   cout << result;
   cin >> a;
   return 0;
}

Теперь считает правильно.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 17:26 
Заслуженный участник
Аватара пользователя


30/01/06
72407
И это и подразумевалось.

letovpowergameisover в сообщении #1159469 писал(а):
Код:
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <conio.h>
using namespace std;

заменить на
    Код:
    #include <stdio>
    #include <iostream>
    #include <math>
    #include <conio>
    using namespace std;
или даже на
    Код:
    // #include <stdio>
    #include <iostream>
    // #include <math>
    // #include <conio>
    using namespace std;


-- 13.10.2016 17:29:13 --

letovpowergameisover в сообщении #1159469 писал(а):
Код:
      result += 1 / temp;

И чисто ради воспитания полезных привычек:
    Код:
          result += 1.0 / temp;
(чтобы не случилось случайно целочисленного деления).

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение13.10.2016, 18:29 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Munin в сообщении #1159476 писал(а):
заменить на
    Код:
    #include <stdio>
    #include <iostream>
    #include <math>
    #include <conio>
    using namespace std;

Как мне подсказали,
    Код:
    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <conio.h> // better not use it
    using namespace std;
Спасибо анониму!

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение14.10.2016, 03:18 
Аватара пользователя


07/02/12
1434
Питер
Возможно, тут в решении хотят еще увидеть приведение к общему знаменателю, что уменьшит накапливающуюся ошибку на делениях при больших n? Хотя может быть и не хотят, если месяц всего..

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение14.10.2016, 03:59 


27/08/16
10197
Код:
double sum = 0;
for (int i = n; i >= 0; i--)
    sum = (sum + 1) / (a + i);

И нужно обработать возможное деление на нуль.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение14.10.2016, 04:07 
Заслуженный участник


09/05/12
25179
letovpowergameisover в сообщении #1159469 писал(а):
Теперь считает правильно.
Вообще-то нет. :-) Ошибка в строчке double temp = a;, на самом деле должно быть double temp = 1.0;

А самое правильное решение см.сообщением выше.

 Профиль  
                  
 
 Re: Си, вычисления
Сообщение14.10.2016, 09:05 
Аватара пользователя


10/10/16
22
realeugene в сообщении #1159636 писал(а):
Код:
double sum = 0;
for (int i = n; i >= 0; i--)
    sum = (sum + 1) / (a + i);

И нужно обработать возможное деление на нуль.


Дааа, я переписал программу на Си, оформил лабу, сдал сейчас и препод мне сказал это.
Странно, я думал, что inf в консоли и так показывает, что идет деление на нуль.
Код на данный момент.
Не понимаю, как сделать, что бы при a=0 и других возможных делениях на 0 выдавало "ошибка, на 0 делить нельзя."
Код:
#include <stdio.h>

double solve(const double a, const int n) {
    double temp = a;
    double result = 1.0 / a;
    for (int i = 1; i <= n; i += 1) {
        temp *= (a + i);
        result += 1.0 / temp;
    }
    return result;
}

int main() {
   int n;
    double a;
    scanf("%lf%i", &a, &n);
    printf("%.4lf\n", solve(a, n));
}


 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 44 ]  На страницу 1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group