Russian Qt Forum
Ноябрь 22, 2024, 22:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: Матьиматика  (Прочитано 23416 раз)
OKTA
Гость
« Ответ #15 : Октябрь 21, 2014, 09:40 »

А что даст корень уравнения?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Октябрь 21, 2014, 10:04 »

А что даст корень уравнения?
Корень и есть "какое y соответствует данному x". Но вот считать его для каждой точки - подозреваю будет накладно. Кстати ф-ция немонотонна и неизвестно правильно ли это вообще.

Да, и возможна ситуация когда одному x соответствует неск y, т.е. результат не определен. Поэтому по-простому-народному выберите диапазон y (напр от 0 до 10), там все монотонно, создайте массив напр 1000 значений x и спокойно находите через lower_bound
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #17 : Октябрь 21, 2014, 10:10 »

А что даст корень уравнения?
Корень и есть "какое y соответствует данному x". Но вот считать его для каждой точки - подозреваю будет накладно. Кстати ф-ция немонотонна и неизвестно правильно ли это вообще.

Да, и возможна ситуация когда одному x соответствует неск y, т.е. результат не определен. Поэтому по-простому-народному выберите диапазон y (напр от 0 до 10), там все монотонно, создайте массив напр 1000 значений x и спокойно находите через lower_bound

Функция как раз монотонна, и однозначна (во всяком случае для x >= 0). Бисекшин - достаточно быстрый метод, никаких "накладно" вы там не заметите..   

Цитировать
Поэтому по-простому-народному выберите диапазон y (напр от 0 до 10), там все монотонно, создайте массив напр 1000 значений x и спокойно находите через lower_bound
А вот так лучше как раз не делать)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Октябрь 21, 2014, 10:49 »

Функция как раз монотонна, и однозначна (во всяком случае для x >= 0). Бисекшин - достаточно быстрый метод, никаких "накладно" вы там не заметите..  
Ну что Вы мне парите Плачущий Пусть бисекшин - простая дихотомия, т.е. деление отрезка пополам (иначе еще хуже). Напр 10 шагов - уже 10 раз вычислена exp, а это разложение в ряд и.т.п.

А вот так лучше как раз не делать)
Аргументы?
Записан
OKTA
Гость
« Ответ #19 : Октябрь 21, 2014, 11:00 »

Посижу, почитаю, поучусь у умных дядек  Смеющийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #20 : Октябрь 21, 2014, 11:07 »

Цитировать
Ну что Вы мне парите Плачущий Пусть бисекшин - простая дихотомия, т.е. деление отрезка пополам (иначе еще хуже). Напр 10 шагов - уже 10 раз вычислена exp, а это разложение в ряд и.т.п.
Вы такую задачку не слышали: Если сложить газету 40 раз, то толщина стопки получится равной расстоянию от земли до луны..
Так вот к чему это я? А теперь прикиньте, какую точность мы получим  за всего каких то 10 итераций бисекшином..

Цитировать
Аргументы?
А они для Вас не очевидны? Давайте сравним две реализации.. С условием, что вычислять функцию нужно с заданной точностью при любом положительном x. Думаю тогда все вопросы сразу отпадут)
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #21 : Октябрь 21, 2014, 11:13 »

Посижу, почитаю, поучусь у умных дядек  Смеющийся
Рано меня ещё в "дядьки" записывать)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Октябрь 21, 2014, 11:34 »

А они для Вас не очевидны? Давайте сравним две реализации.. С условием, что вычислять функцию нужно с заданной точностью при любом положительном x. Думаю тогда все вопросы сразу отпадут)
bisect требует диапазона аргумента (в данном случае y). Откуда Вы его возьмете? Ну напр y = 50, exp(50) - уже "слишком много" чтобы реально использоваться в задаче. Поэтому разговоры о "любом положительном x" неуместны. Более того, на практике часто вообще интересен диапазон [0..1]. Так что давайте реалистичнее, тогда пожалуйста - сравним  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #23 : Октябрь 21, 2014, 11:47 »

Цитировать
Откуда Вы его возьмете? Ну напр y = 50, exp(50) - уже "слишком много" чтобы реально использоваться в задаче.
Верхнюю границу y можно оценить, и поверьте, она  50ти никогда не будет равна, для любого разумного x..
Так что разговор уместен)

Цитировать
Более того, на практике часто вообще интересен диапазон [0..1].
Это Вы с потолка опять взяли? А мне нужно график, например от 0 до 1000000.. И что мне с вашим от 0 до 1 делать? Ммм?

 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Октябрь 21, 2014, 12:02 »

Это Вы с потолка опять взяли? А мне нужно график, например от 0 до 1000000.. И что мне с вашим от 0 до 1 делать? Ммм?
Я говорю о значениях аргумента (y). exp(100000..) вернет nan. Наверное Вы имеете ввиду график х(y) где макс x - достаточно большое. Ну что ж, потрачу больше памяти чтобы добиться нужной точности. Да, если Вы не поняли (судя по постам) то массив строится 1 раз на этапе предрасчета. Поэтому соревноваться с ним в скорости поиска довольно глупо  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #25 : Октябрь 21, 2014, 13:32 »

Цитировать
Я говорю о значениях аргумента (y). exp(100000..) вернет nan.
Я понимаю, о чём Вы говорите.. Я тоже говорю о значениях y..  Ситуации с nan никогда не возникнет, поскольку верхняя граница y для всех разумных x, будет порядка 10, а то и меньше.. Я имею в виду функцию y(x)

Цитировать
Ну что ж, потрачу больше памяти чтобы добиться нужной точности.
Поэтому соревноваться с ним в скорости поиска довольно глупо
Давайте, проверим) Выкладывайте свою реализацию "по-народному", а я выложу свою) 
Условие прежние посчитать y(x) для любого положительного x с заданной точностью)

  
« Последнее редактирование: Октябрь 21, 2014, 13:49 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #26 : Октябрь 21, 2014, 19:50 »

Похоже, народное решение мы не увидим.. Ну да ладно)

Скажу несколько слов о производительности метода bisect..
Написал пробный тест, где сравнивается скорость построения графика нашей функции (exact) y(x) (обратной к y*exp(y))
и очень на неё похожей функции (approx) y = log(1 + x)/1.35. На приаттаченом рисунке они обе изображены.

Переменная x проходит от 0 до 10000 с шагом dx = 1. Результат записывается в файл.

Исходник с замером времени:
Код
C++ (Qt)
#include <iostream>
#include <fstream>
#include <chrono>
 
#include <specmath/roots.h>
 
 
template <class T>
T exact_func(const T & x, const T & err = 0.000001)
{
   static const T e = exp(1);
 
   const T ln_x = log(x);
   const T min = (x < e) ? 0 : 1;
   const T max = (x < e) ? 1 : ln_x;
 
   return specmath::bisect([&](const T& s) { return (x < e) ? (x - s * exp(s)) : (ln_x - s - log(s)); },  min, max, err);
}
 
template <class T>
T approx_func(const T & x)
{
   return log(1 + x)/1.35;
}
 
int main()
{
   double x = 0;
   const double xmax = 10000;
   const double dx = 1;
 
 
   std::ofstream out1("data1.txt");
   std::ofstream out2("data2.txt");
 
   auto start = std::chrono::high_resolution_clock::now();
   while (x < xmax)
   {
       out1 << x << " " << exact_func(x) << std::endl;
       x += dx;
   }
   auto stop = std::chrono::high_resolution_clock::now();
 
   auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(stop-start).count();
 
   std::cout << " bisection: total time = " << elapsed << "ms" << std::endl;
 
 
 
   x = 0;
   start = std::chrono::high_resolution_clock::now();
   while (x < xmax)
   {
       out2 << x << " " << approx_func2(x) << std::endl;
       x += dx;
   }
   stop = std::chrono::high_resolution_clock::now();
 
   elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(stop-start).count();
 
   std::cout << "aprox func: total time = " << elapsed << "ms" << std::endl;
 
   return 0;
}
 
 

Результаты трёх прогонов следующие:
Код
Bash
bisection: total time = 58ms
aprox func: total time = 50ms
 
bisection: total time = 58ms
aprox func: total time = 50ms
 
bisection: total time = 58ms
aprox func: total time = 51ms
 

Как видно, разница ничтожна..  
"Народный" вариант от igors однозначно проиграл бы по памяти (это мягко говоря), да и по скорости тоже есть сомнения..
Так что делаем выводы..

ЗЫ В примере выше, вместо boost::bisect использовалась более  быстрая её версия.. Но сути это не меняет..
« Последнее редактирование: Октябрь 21, 2014, 20:06 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Октябрь 21, 2014, 20:32 »

Что-то не то, не так. В approx всего лишь один log, в exact уже до bisect тот же log плюс сам bisect чего-то весит, сколь бы чудесным он ни был. Вычислительная нагрузка в exact по меньшей мере в неск раз больше. Чего же это времена отличаются ненамного? Напечатайте сколько раз зовется функтор bisect, тогда будет ясно

f = ln_x - s - log(s)  // прологарифмированное исходное
f(1) = log(1) - 1 - log(1) = -1  // нижний предел
f(log(x)) = log(x) - x - log(log(x)) < 0 // верхний предел

Похоже bisect'у нечего считать т.к. оба предела < 0

Похоже, народное решение мы не увидим..
Я найду время, просто "не сию минуту" - есть и другие дела  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #28 : Октябрь 21, 2014, 20:41 »

Цитировать
Что-то не то, не так. В approx всего лишь один log, в exact уже до bisect тот же log плюс сам bisect чего-то весит, сколь бы чудесным он ни был. Вычислительная нагрузка в exact по меньшей мере в неск раз больше. Чего же это времена отличаются ненамного? Напечатайте сколько раз зовется функтор bisect, тогда будет ясно
Ну вообще то, эти результаты: два графика были построены после запуска этого примера.. Строится всё корректно) Время тоже считается честно)  

Цитировать
f = ln_x - s - log(s)  // прологарифмированное исходное
f(1) = log(1) - 1 - log(1) = -1  // нижний предел
f(log(x)) = log(x) - x - log(log(x)) < 0 // верхний предел

Похоже bisect'у нечего считать т.к. оба предела < 0
Нет, если внимательно посмотреть, то в самой лямбде тоже проверяется условие (x < e) и в зависимости от него выбирается своя схема..
Там всё корректно, иначе результат (график) не получился бы)  

Поменял местами exact и approx.. Результаты не изменились..
« Последнее редактирование: Октябрь 21, 2014, 20:44 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #29 : Октябрь 21, 2014, 20:50 »

Приаттачиваю проект, на всякий случай..
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.096 секунд. Запросов: 23.