LINUX.ORG.RU

Определение точек разрыва функции

 , ,


0

3

Утро доброе.

Задача: рисовать график.

Нынешняя реализация: Узнаем отрезок на Ox на котором надо считать функцию, например от -9 до 15.

Скармливаем функцию парсеру, а затем заставляем считать от -9 до 15, с шагом, например, 0.25.

Аккуратно записываем все вычисления в списочек вида:

{x1,y1}, {x2, y2}, {x3, y3}, ... {xn, yn}

Затем бежим по нашему списку и рисуем линии:

draw_line(x1,y1, x2,y2)
draw_line(x2,y2, x3,y3)
draw_line(x3,y3, x4,y4)
...
draw_line(x(n-1),y(n-1), xn,yn)

Проблема: не все функции непрерывные, а данная реализация всегда рисует непрерывно.

Вопрос: Как находить эти самые точки разрыва? Или нынешняя реализация дико ущербна и надо её переделать? Если да, то с радостью приму советы как.

какие элементарные операции или другие функции могут входит в выражение этой функции?

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, log2, log10, log, ln, exp, sqrt, sign (sign function -1 if x<0; 1 if x>0), rint (округление до целого), abs

min, max, sum, avg <-- принимают список аргументов

Всякие плюс-минусы-умножить, возведение в степень(^) ну и логические операции(и, или, больше-меньше\или равно, не равно, равно)

BruteForce ★★★
() автор топика

уменьшая шаг дискретизации следи за увеличением производной в точках. если где-то растет слишком быстро, локализовываешь и на этом месте дальше уменьшаешь шаг.

ну или вообще на всем интервале делаешь адаптивный шаг.

dikiy ★★☆☆☆
()
Ответ на: комментарий от BruteForce

можно аналитически попробовать автоматизировать. нетривиально для всяких sin и rint, зато эффективно и не зависит от скорости роста.

MyTrooName ★★★★★
()
Ответ на: комментарий от dikiy

Благодарю за ответ.

если где-то растет слишком быстро, локализовываешь и на этом месте дальше уменьшаешь шаг.

Уменьшаю шаг, уменьшаю... И до какой степени?

ну или вообще на всем интервале делаешь адаптивный шаг.

Ну, а как его мне высчитывать есть идеи?

BruteForce ★★★
() автор топика
Ответ на: комментарий от dikiy

1) разрыв бывает устранимый.

2) sign(x)*sqrt(abs(x)), к примеру, 0 в разрыве не имеет, но таким способом его там можно задетектить случайно. то, что в 0 есть значение, еще ни о чем не говорит

MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от MyTrooName

Благодарю за ответ.

если где-то растет слишком быстро, локализовываешь и на этом месте дальше уменьшаешь шаг.
Уменьшаю шаг, уменьшаю... И до какой степени?

до заранее фиксированной величины. послее ее превышения считаешь, что в этой точке разрыв.

ну или вообще на всем интервале делаешь адаптивный шаг.

Ну, а как его мне высчитывать есть идеи?

делаешь шаг пропорционльным изменению производной между итерациями.

dikiy ★★☆☆☆
()
Ответ на: комментарий от MyTrooName

1) разрыв бывает устранимый.

бывает. Но его численным методом не задетектить в принципе. Поэтому не рассматриваем.

2) sign(x)*sqrt(abs(x)), к примеру, 0 в разрыве не имеет, но таким способом его там можно задетектить случайно. то, что в 0 есть значение, еще ни о чем не говорит

тогда вместе с производной следим за изменениями значений функции.

dikiy ★★☆☆☆
()
Ответ на: комментарий от BruteForce

если |yT-yG| <= 1, то не надо, визуально точки и так соединены. иначе еще уменьшаешь шаг раза в два. и так пока либо |yT-yG| не перестанет заметно уменьшаться (можно считать, что функция разошлась), либо пока точки yT и yG не станут соседними (|yT-yG| <= 1)

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

Благодарю.

Из всего выше написанного: делаем динамический шаг на основе разрешения картинки. Если разница между точками <= 1 px. то не рисуем линию.

Попробую.

BruteForce ★★★
() автор топика

Вопрос: Как находить эти самые точки разрыва?

Очевидно, нули ф-ции 1/y(x).

iVS ★★★★★
()
Ответ на: комментарий от iVS

sign (sign function -1 if x<0; 1 if x>0)

Но с такой ф-цией не прокатит.

iVS ★★★★★
()

Всех благодарю, проблема решена следующим образом: Функция старой реализации была разбита на три. 1) Функция, возвращающая список всех просчитанных точек.

2) Функция, которая разбивала возвращаемый первой функцией список на ломаные линии. Условие:

if (
	    abs(
				current->at(i-1).x()
				-
				current->at(i).x()) <= 0
		    ||
		    abs(
				current->at(i-1).y()
				-
				current->at(i).y()) <= 0
		    ||
		    abs(
				current->at(i-1).y()
				-
				current->at(i).y()) > height_
		    ||
		    abs(
				current->at(i-1).x()
				-
				current->at(i).x()) > width_
		    )
Где height_ и width_ это высота и длина изображения в пикселях.

При выполнении условия функция удаляет точку из ломаной линии и делит её на две ломаные линии.

3) Функция, которая рисует все ломаные линии.

BruteForce ★★★
() автор топика
Ответ на: комментарий от BruteForce

abs(...)<=0

  • < - как?
  • = - зачем?

abs(...x()-...x()) > width_

а смысл?

anonymous
()

А может, как в школе? Берём производную от функции, и там, где производная меняет знак, и будут искомые точки разрыва?

tiinn ★★★★★
()

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

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.