Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: нахождение всех нулей функции  (Прочитано 7795 раз)
0 Пользователей и 1 Гость смотрят эту тему.
phabion
Интересующийся

ru
Offline Offline

« : 17-10-2010 06:55 » 

Здравствуйте!
Задача у меня такая: данная функция X(t)=5.6*cos(t)+ 2.4*cos(7*t/3); Y(t)=5.6*sin(t) - 2.4*sin(7*t/3); Требуется найти все нули функции (то есть найти точки c координатой (X,0))
Я написал программку:

Код: (C++)
#include <math.h>
#include <iostream.h>
#include <conio.h>
#define dt M_PI/1000
double X(double t)
{
        return 5.6*cos(t)+ 2.4*cos(7*t/3);
}
double Y(double t)
{
        return 5.6*sin(t) - 2.4*sin(7*t/3);
}
void FindZeroPoint (double left, double right)
{
        double t;
        double array1[100], array2[100];
        int count=0;
        for(t=left;t<=right;t+=dt)
        {
                if(Y(t)*Y(t+dt)<0){
                        count++;
                        array1[count]=X(t);
                        array2[count]=Y(t);
                }
        }
        cout<<"count="<<count<<endl;
        for (int i=0; i <= count-1; i++) {                                                                     
                cout<<"("<<array1[count]<<";"<<array2[count]<<")";
        }      
}
int main(void)
{
        FindZeroPoint(0,6*M_PI);
        getch();
        return 0;
}

И результат выполнения этой программки таков (рисунок 1)
График этой функции таков (рисунок 2)
Так что, я не могу понять что не правильно в функции void FindZeroPoint (double left, double right).
Буду благодарен за любой ответ!

* Untitled3.png (100.9 Кб - загружено 663 раз.)
« Последнее редактирование: 17-10-2010 07:00 от RXL » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 17-10-2010 07:10 » 

phabion, почему ты думаешь, что результат неверный?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #2 : 17-10-2010 07:16 » 

phabion,

Y=0 => найти все t, при которых

5.6*sin(t) = 2.4*sin(7*t/3);

эти t подставить в X(t)

Записан

phabion
Интересующийся

ru
Offline Offline

« Ответ #3 : 17-10-2010 12:49 » 

phabion, почему ты думаешь, что результат неверный?
Видно что результат не верный так как функция даёт 6 одинаковых точек ( а на графике мы видим что имеются 6 нулей, в которых 2 пары точек совпадают)

Добавлено через 4 минуты и 43 секунды:
phabion,

Y=0 => найти все t, при которых

5.6*sin(t) = 2.4*sin(7*t/3);

эти t подставить в X(t)


мы этого не можем сделать, так как в каждом цикле мы увеличиваем t на dt, то есть значения t дискретные.
Если бы мы могли проверить каждое реальное число, то мы бы могли найти t, при которых Y(t)=0.
« Последнее редактирование: 17-10-2010 12:54 от phabion » Записан
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 17-10-2010 13:20 » 

мы этого не можем сделать, так как в каждом цикле мы увеличиваем t на dt, то есть значения t дискретные.
Если бы мы могли проверить каждое реальное число, то мы бы могли найти t, при которых Y(t)=0.

В приведенном фрагменте:
Код: (C++)
...
        for(t=left;t<=right;t+=dt)
        {
                if(Y(t)*Y(t+dt)<0){
                        count++;
                        array1[count]=X(t);
                        array2[count]=Y(t);
                }
        }
...
решение находится с дискретом dt. При этом гарантируется лишь то, что функция меняет знак на интервале [t, t+dt], а не то, что она обращается в нуль.

В способе, который предложил Алексей1153++, можно найти корни уравнения с любой заданной точностью, причем гораздо эффективнее, чем перебирая значения аргумента с мелким шагом, и точнее, чем дискретность шага.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Sands
Помогающий

ua
Offline Offline

« Ответ #5 : 17-10-2010 16:37 » 

Там просто ошибка в коде вывода. Код
Код:
for (int i=0; i <= count-1; i++) {
                cout<<"("<<array1[count]<<";"<<array2[count]<<")";
}
надо заменить на
Код:
for (int i=0; i <= count-1; i++) {
                cout<<"("<<array1[ i ]<<";"<<array2[ i ]<<")";
}
Однако соглашусь с остальными, что стоит для начала поискать нули функции
Y(t)=5.6*sin(t) - 2.4*sin(7*t/3)
а потом найденные t подставить в формулу для X(t)

P.S Численных методов для нахождения нулей функции - немеряно. Простейший - метод бисекции. Думаю, дальше поможет поиск.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #6 : 17-10-2010 17:50 » 

если брать конкретно выражение

5.6*sin(t) = 2.4*sin(7*t/3);

, то можно определить период повторения. Начало периода в t=0, длина периода L такова, что она кратна 2*Пи и 2*Пи*7/3

наименьший такой период - 42*Пи

(если я не ошибся где-то, но вроде нет ))) )
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines