2014 dxdy logo

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

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




На страницу 1, 2, 3  След.
 
 Си, вычисления
Сообщение13.10.2016, 16:04 
Аватара пользователя
Дано натуральное 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 
Аватара пользователя
Подсказка по алгоритму: можно temp не считать каждый раз заново, а взять почти готовый с предыдущего прохода цикла.

 
 
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:13 
Вы считаете $\frac1a+\frac1a+\frac1{a(a+1)}+\dots+\frac1{a(a+1)\dots(a+n-1)}$, по-моему.

 
 
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:13 
Аватара пользователя
А так, ошибка в условиях циклов, надо разобраться с нумерацией.

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

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

 
 
 
 Re: Си, вычисления
Сообщение13.10.2016, 16:19 
Аватара пользователя
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 
Аватара пользователя
Путаница с индексами циклов - типична для начинающих. Особенно сбивает то, что в стандартной сишной шапке цикла
    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 
letovpowergameisover в сообщении #1159451 писал(а):
Аааааааааааааа, спасибо. Понял.
Странно. :-) Я там опечатался, имелось в виду n=3. Сейчас в своем сообщении я это исправил.

 
 
 
 Re: Си, вычисления
Сообщение13.10.2016, 17:07 
Аватара пользователя
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 
Аватара пользователя
И это и подразумевалось.

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 
Аватара пользователя
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 
Аватара пользователя
Возможно, тут в решении хотят еще увидеть приведение к общему знаменателю, что уменьшит накапливающуюся ошибку на делениях при больших n? Хотя может быть и не хотят, если месяц всего..

 
 
 
 Re: Си, вычисления
Сообщение14.10.2016, 03:59 
Код:
double sum = 0;
for (int i = n; i >= 0; i--)
    sum = (sum + 1) / (a + i);

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

 
 
 
 Re: Си, вычисления
Сообщение14.10.2016, 04:07 
letovpowergameisover в сообщении #1159469 писал(а):
Теперь считает правильно.
Вообще-то нет. :-) Ошибка в строчке double temp = a;, на самом деле должно быть double temp = 1.0;

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

 
 
 
 Re: Си, вычисления
Сообщение14.10.2016, 09:05 
Аватара пользователя
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  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group