Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/12: Рейтинг темы: голосов - 12, средняя оценка - 4.50
Deryck
5 / 5 / 0
Регистрация: 01.12.2010
Сообщений: 109
1

Погрешность при вычислении синуса

26.02.2012, 19:57. Просмотров 2237. Ответов 12
Метки нет (Все метки)

вот исходный код программы(вычисляет синус через многочлен Тейлора):
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <stdlib.h>
#define PI 3.14159265358979323846
 
 
int factorial (int n){
   int i, res;
   if (n<=1){
       res=1;
   }
   else{ 
       res=factorial(n-1)*n;
   }      
   return(res);
}
 
float radians(int deg){
    float rad;
    rad = deg * PI/180;
    return(rad);
}
 
float degree (float x, int n) {
    float res;
    if (n<=1){
        res=x;
    }
    else {
        res=degree(x, n-1)*x;
    }
    return (res);
}
 
float sinus (float x){
   int i, sign, fac;
   float rad, t, res;
   t=radians(x);
   res=0;
   sign=1;
   for (i=1; i<=30; i++){
       if (i%2 != 0){
         res+=sign*(degree(t, i) / factorial(i));
         sign=1-sign?1:-1;
       }
   }
   return (res);
}
 
int main() {
    int i;
    for (i=30; i<=90; i++){
        printf("sinus %d = %.7f\n", i, sinus(i));
    }
    return (EXIT_SUCCESS);
}
sin90=0.9994085, отличие конечно небольшое но все таки... помогите найти погрешность?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.02.2012, 19:57
Ответы с готовыми решениями:

Программа выдает ноль при любых условиях при вычислении выражения
помогите решить программу на си, у меня выдает неправильный результат((...

Ошибка при вычислении функции
здравствуйте Программисты.... можете мне помочь, вот я написал программу, и она...

Ошибки при вычислении выражения
Помогите почему не работает #include&lt;conio.h&gt; #include&lt;math.h&gt;...

Ошибка при вычислении log(x)
Операционная система GNU/Linux, дистрибутив Kubuntu 9.10, компилятор gcc. ...

Ошибка при вычислении выражения
Даны натуральные числа N и M. Вычислить F=M!+N!/(N+M)! Программа должна...

12
Питекантроп
249 / 143 / 21
Регистрация: 14.06.2010
Сообщений: 340
26.02.2012, 22:24 2
погрешностью можно считать degree(t, i) / factorial(i)
Вообще, программа составлена неэффективно
0
Deryck
5 / 5 / 0
Регистрация: 01.12.2010
Сообщений: 109
27.02.2012, 17:16  [ТС] 3
сравнился с формулой... в чем именно погрешность?
да кстати тот же вариант программы но без функций(куча циклов в main), работает идеально.
0
Миниатюры
Погрешность при вычислении синуса  
-=ЮрА=-
Заблокирован
Автор FAQ
27.02.2012, 17:34 4
Deryck, настоятельно рекомендую прочесть http://www.cyberforum.ru/faq/thread436065.html#post2452211
По поводу вашей погрешности - существует погрешность разложения(т.е заменяя функцию на ряд мы уже вносим некую погрешность), причём при меньших значениях аргумента погрешность будет меньше. Попробуйте посчитать по вашему алгоритму sin(0.9) и sin(0.1) и sin(0.01) - будете удивлены!

Добавлено через 1 минуту
Deryck, посмотрев ваш код скажу, что находить факториал на каждом шаге - ну очень нерационально, заменяйте всё итератором
1
Deryck
5 / 5 / 0
Регистрация: 01.12.2010
Сообщений: 109
27.02.2012, 18:04  [ТС] 5
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Deryck, настоятельно рекомендую прочесть http://www.cyberforum.ru/faq/thread436065.html#post2452211
По поводу вашей погрешности - существует погрешность разложения(т.е заменяя функцию на ряд мы уже вносим некую погрешность), причём при меньших значениях аргумента погрешность будет меньше. Попробуйте посчитать по вашему алгоритму sin(0.9) и sin(0.1) и sin(0.01) - будете удивлены!

Добавлено через 1 минуту
Deryck, посмотрев ваш код скажу, что находить факториал на каждом шаге - ну очень нерационально, заменяйте всё итератором
Ну по поводу факториала, я понимаю что это не рационально, но задание составить программу по функциям, мне показалось что так будет нагляднее, каждая функция выполняет свою часть. В принципе в этом задании эффективность не так уж и важна. Тема про ряды действительно интересно(по ней и матан сдавать можно), но вот что меня смущает, есть еще одна программа, которая работает идеально:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <stdlib.h>
#define PI 3.14159265358979323846
 
int main() {
    int i, j, sign, deg;
    float rad, sinus, x, fac, sum;
    for (deg=1; deg<=90; deg++){
       rad = deg * (PI/180);
       sinus=0;
       sign=1;
       for (i=1; i<=30; i++){
           if (i%2 != 0){
           fac=1;
           x=1;
           for (j=1; j<=i; j++){
               fac*=j;
               x*=rad;
           } 
           sum=sign*(x/fac);  
           sinus+=sum;
           sign=1-sign?1:-1;
           }
       }
       printf("sinus %d = %f \n", deg, sinus);
    }
    return (EXIT_SUCCESS);
}
алгоритм тот же, за исключением отсутствия рекурсии... но сами рекурсивные функции работают верно...
можно ли считать погрешность, полученную в первом варианте программы, допустимой для данного алгоритма?
0
-=ЮрА=-
Заблокирован
Автор FAQ
27.02.2012, 18:16 6
Deryck, у вас же 30 членов разложения, таким образом точность вашего алгоритма fabs(30-й член разложения) посчиатайте(чесно у вас небольшая каша в коде), где счиается отдельный член разложения сложно увидеть - если вы его так считаете

Цитата Сообщение от Deryck Посмотреть сообщение
sign*(x/fac);
- то тогда точность fabs(x/fac), я не проверял но помоему вы неверно посчитали итератор...
1
-=ЮрА=-
Заблокирован
Автор FAQ
27.02.2012, 18:30 7
Deryck, вот ваш итератор
http://www.cyberforum.ru/cgi-bin/latex.cgi?{a}_{n} = \frac{{(-1)}^{n}}{(2*n + 1)!}*{x}^{2*n + 1}
http://www.cyberforum.ru/cgi-bin/latex.cgi?{a}_{n + 1} = \frac{{(-1)}^{n + 1}}{(2*(n + 1) + 1)!}*{x}^{2*(n + 1) + 1} = \frac{{(-1)}^{n + 1}}{(2*n + 2)!}*{x}^{2*n + 2}
http://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{{a}_{n + 1} }{{a}_{n}} = \frac{\frac{{(-1)}^{n + 1}}{(2*n + 2)!}*{x}^{2*n + 2}}{\frac{{(-1)}^{n}}{(2*n + 1)!}*{x}^{2*n + 1}} = (-1)*{x}^{2}*\frac{(2*n + 1)!}{(2*n + 2)!} = (-1)*{x}^{2}*\frac{(2*n + 1)!}{(2*n + 1)!*(2*n + 2)}
Как видите итератор весьма и весьма прост
http://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{{a}_{n + 1} }{{a}_{n}} = \frac{(-1)*{x}^{2}}{(2*n + 2)}
Код ниже считает синус через итератор и оценивает погрешность разложения
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <math.h>
 
//Ïðîòîòèï ГЅГІГ*ëëîГ*îé ГґГіГ*êöèè ïîëüçîâГ*òåëÿ
//âîçâðГ*Г№Г*åìîå Г§Г*Г*Г·ГҐГ*ГЁГҐ - Г§Г*Г*Г·ГҐГ*ГЁГҐ ch(x) Гў òî÷êå Гµ
double Y(double x)
{
        return sin(x);
}
 
//ÔóГ*êöèÿ âîçâðГ*Г№Г*ГҐГІ Г§Г*Г*Г·ГҐГ*ГЁГҐ ñóììû ðÿäГ* x^2k/(2*k)!
//Г°Г*Г±Г±Г·ГЁГІГ*Г*Г*îå Г± îòГ*îñèòåëüГ*îé ïîãðåøГ*îñòüþ e
double S(double x)
{
        double ak = x, sum = 0;
        long k = 0;
        //ÄåëГ*ГҐГ¬ ГўГ*ГёГҐ Г°Г*çëîæåГ*ГЁГҐ Г± 30-Гѕ ÷ëåГ*Г*ìè
        while(k <= 30)
        {
                sum += ak;
                ak  *= (-1.0)*pow(x,2)/(2*k + 2);
                //(-1)*pow(x,2)/(2*k + 2) - Г*Г*Гё ГЁГІГҐГ°Г*òîð
                //ГЄГ*ГЄ âèäèì ГҐГЈГ® Г§Г*Г*Г·ГҐГ*ГЁГҐ Г§Г*ГўГЁГ±ГІ îò k, 
                //Г*Г® Г°Г*Г±Г·ВёГІГ*Г*Гї ôîðìóëГ* ïîçâîëÿåò îáîéòèñü ГЎГҐГ§ âîçâåäåГ*ГЁГї
                //Гў Г±ГІГҐГЇГҐГ*Гј 2*k ГЁ èñêëþ÷èòü îïåðГ*öèþ Г*Г*õîæäåГ*ГЁГї ГґГ*êòîðèГ*Г«Г*
                k++;
        }
        return sum;
}
 
int main()
{
        double e = 0, x = 0;
        while(1)//ÄåëГ*Гѕ ГЎГҐГ±ГЄГ®Г*ГҐГ·Г*ûé ââîä
                //äëÿ Г§Г*âåðøåГ*ГЁГї Г°Г*áîòû ïðîñòî Г§Г*êðûâГ*ГҐГ¬ îêГ*Г® ГЄГ®Г*ñîëè
        {
                printf("Enter x : ");scanf("%lf",&x);
                printf("Y(x) = %lf\n",Y(x));
                printf("S(x) = %lf\n",S(x));
                e = fabs(100.0*(Y(x) - S(x))/Y(x));
                printf("Error of calculations : %.2f %\n",e);
        }
        return 0;
}
1
Миниатюры
Погрешность при вычислении синуса  
-=ЮрА=-
Заблокирован
Автор FAQ
27.02.2012, 18:38 8
Результат работы - яркий пример влияния величины аргумента на значение функции полученной через ряд
PS:Deryck, сравните ваш код с моим и скажите как проще и легче считать пользясь итератором или же вычисляя факториал на каждом шаге? И это вы ограничились 30-ю членами ряда
Цитата Сообщение от Deryck Посмотреть сообщение
for (i=1; i<=30; i++)
, а если бы взяли их с 1000-чу как бы тогда ваша програмка считала???Она просто бы опрокинулась на факториале, вот поэтому и оговаривал что итератор избавляет наши программы от трудоёмкости и нерационального использования ресурсов. Далее уже выбор за вами...

Добавлено через 3 минуты
Теперь о погрешности sin(90 градусов) = 1
В расчёте
Цитата Сообщение от Deryck Посмотреть сообщение
sin90=0.9994085
Таким образом погрешность составила
100%*|(0.9994085 - 1)/1| ~ 0.06% Что весьма точно
1
Deryck
5 / 5 / 0
Регистрация: 01.12.2010
Сообщений: 109
27.02.2012, 19:35  [ТС] 9
Спасибо огромное. с итератором в принципе разобрался, спасибо за объяснения.
0
Том Ардер
Модератор
Эксперт по математике/физике
3843 / 2455 / 328
Регистрация: 15.06.2009
Сообщений: 4,502
27.02.2012, 20:05 10
Цитата Сообщение от Deryck Посмотреть сообщение
for (i=1; i<=30; i++)
{ if (i%2 != 0)
{
res+=sign*(degree(t, i) / factorial(i)); sign=1-sign?1:-1;
}
}
Ряд знакопеременный, зн. погрешность меньше последнего отброшенного слагаемого. Для http://www.cyberforum.ru/cgi-bin/latex.cgi?\sin \left(\frac{\pi }{2} \right) это http://www.cyberforum.ru/cgi-bin/latex.cgi?{\left(\frac{\pi }{2} \right)}^{31} /31!\sim {10}^{-28}

Цитата Сообщение от Deryck Посмотреть сообщение
sin90=0.9994085
такая точность не оправдывает затраченных усилий.

Главный источник ошибок - вычисление факториала, уже при i >=17 factorial(i) выходит за рамки дипазона машинного целого и в памяти оказывается мусор, результат - непредсказуемый.
Каждое слагаемое нужно вычислять рекуррентно, тогда проблем с переполнением не будет.
(См. посты -=ЮрА=-, )

И вместо float нужно double.
0
Deryck
5 / 5 / 0
Регистрация: 01.12.2010
Сообщений: 109
27.02.2012, 20:20  [ТС] 11
Всем, спасибо. Наконец то довел ее до ума
0
Том Ардер
Модератор
Эксперт по математике/физике
3843 / 2455 / 328
Регистрация: 15.06.2009
Сообщений: 4,502
27.02.2012, 20:20 12
-=ЮрА=-, ошибка в итераторе для синуса:

2(n+1)+1 = 2n+3 (было 2n+2)
1
-=ЮрА=-
27.02.2012, 22:18     Погрешность при вычислении синуса
  #13

Не по теме:

Том Ардер, да в знаменателе нужно было
(2(n + 1) + 1)! = (2*n + 3)! = (2*n + 1)!*(2n + 2)(2n + 3), т.е знаменателе нужен ещё сомножитель
(2n + 3)(поспешил с привдением подобных), к сожаленю невнимательность это мой грех...

0
27.02.2012, 22:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.02.2012, 22:18
Привет! Вот еще темы с ответами:

Ошибка при вычислении произведения
помогите, не могу найти ошибку.Не считает произведение S при С&lt;0...

Несоответствие результатов при вычислении функции
Доброе время суток. Прошу помощи у знающих людей. Есть программа вычисляющая...

Проверка на переполнение при вычислении выражения
Доброго времени суток. Помогите пожалуйста с одним вопросом. Имеется задание:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru