powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Оцените подход к линейной интерполяции значения функции
7 сообщений из 7, страница 1 из 1
Оцените подход к линейной интерполяции значения функции
    #38062304
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я изложу вопрос и как я его решил. Хотелось бы узнать ваши комментарии. Что можно исправить, дополнить и есть ли вообще подход проще и компактнее.



Пишу свою функцию интерполяции. На вход поступает две последовательсности - значений аргумента функции и значений функции. Также на вход подаётся заданное значение аргумента, не совпадающее ни с одним из значений последовательности аргументов, но лежащее в пределах этой последовательности. Нужно найти интерполированное значение функции, соответствующее заданному аргументу. Линейная интерполяция.

Я сделал так - просто перебираю входящую последовательность аргументов функции, пока не найду значение аргумента (это будет "текущее значение аргумента"), бОльшее заданного аргумента. После этого беру текущее значение аргумента и предыдущее - заданное будет лежать между ними - и, соответственно, текущее и предыдущее значения функции, и интерполирую линейно по уравнению прямой по двум точкам .

Всё просто, но вопрос в условии цикла перебора аргументов -
авторпока не найду значение аргумента , бОльшее заданного аргумента
Это будет работать, только если входящая последовательность аргументов возрастает. А если она убывает? Тогда что делать? Хотелось бы написать максимально компактную функцию, не растекаясь кодом по логике.

Я придумал такой вариант решения - принудительно упорядочивать последовательность аргументов по возрастанию. Известно, что входящая последовательность аргументов может либо монотонно возрастать, либо монотонно убывать. Также известно, что входящая последовательность значений функции соответствует входящей последовательности аргументов функции. Поэтому я могу вообще ограничиться простым реверсом входящих аргументов, если любые два из них не удовлетворяют условию, что аргумент с бОльшим индексом больше аргумента с меньшим индексом. Соотетственно, надо сделать реверс и последовательности значений функции.

Вот код


Код: 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.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
/// <summary>
/// Находит линейно интерполированное значение функции между двумя точками.
/// </summary>
/// <param name="arg1">Значение первого аргумента функции.</param>
/// <param name="arg2">Значение второго аргумента функции.</param>
/// <param name="func1">Значение функции при аргументе arg1.</param>
/// <param name="func2">Значение функции при аргументе arg2.</param>
/// <param name="arg">Значение аргумента, при котором нужно найти интерполированное значение функции. 
/// Значение arg лежит между значениями arg1 и arg2, при этом не важно, какое из этих значений аргумента больше другого, а какое меньше.</param>
/// <returns></returns>
private static double Interpolation(double arg1, double arg2, double func1, double func2, double arg)
{
	return
		(func2 - func1) *
		(arg - arg1) /
		(arg2 - arg1) +
		func1;
}

/// <summary>
/// Находит линейно интерполированное значение функции между двумя точками, лежащими в указанных пределах области определения (области значений аргумента функции) и 
/// области значений функции.
/// </summary>
/// <param name="args">Последовательность значений аргумента функции, в пределах которой находится параметр arg, 
/// по которому нужно найти интерполированное значение функции.</param>
/// <param name="funcs">Последовательность значений функции, в пределах которой нужно найти интерполированное значение функции.</param>
/// <param name="arg">Значение аргумента, при котором нужно найти интерполированное значение функции.</param>
/// <returns></returns>
public static double Interpolation(List<double> args, List<double> funcs, double arg)
{
	if (args.Count < 2)
	{
		throw new Exception("Входящая последовательность аргументов не может иметь менее двух элементов.");
	}

	if (args.Count != funcs.Count)
	{
		throw new Exception("Число элементов входящей последовательности аргументов должно быть равно числу элементов входящей последовательности значений фукнции.");
	}

	// Алгоритм будет работать, только если входящая последовательность аргументов монотонно возрастает.
	// Если она будет монотонно убывать (последовательность аргументов передали в обратном порядке), то алгоритм работать не будет.
	// Этого можно избежать, если принудительно упорядочивать последовательность аргументов по возрастанию, если изначально она упорядочена по убыванию.
	// Если порядок последовательности аргументов был изменён, то порядок последовательности значений функции тоже должен быть изменён.

	// Определяем, отсортирована ли исходная последовательность аргументов по возрастанию. Для этого достаточно проверить, больше ли любой из её элементов с бОльшим
	// индексом любого из её элементов с меньшим индексом. Если исходные аргументы находятся в порядке возрастания, то ничего не делать с исходными последовательностями
	// и применять алгоритм интерполяции. В противном случае поменять порядок обеих входящих последовательностей (и значений аргументов фукнции, и значений функции),
	// после чего применять алгоритм интерполяции.
	if (args[0] > args[1])
	{
		args.Reverse();
		funcs.Reverse();
	}

	// Алгоритм перебирает все значения аргумента функции, пока не превысит заданное значение аргумента (arg). При превышении заданного значения аргумента
	// алгоритм берёт текущее и предыдущее значения аргумента и функции - при этом значение аргумента arg и значение функции при этом аргументе, которое
	// надо найти, окажутся между этими выбранными значениями - и находит значение функции при аргументе arg методом линейной интерполяции.
	for (int i = 0; i < args.Count; i++)
	{
		// Если текущее значение аргумента равно значению аргумента, при котором нужно найти интерполированное значение функции, то ничего интерполировать ненадо,
		// и надо просто вернуть значение функции, соответствующее текущему значению аргумента.
		if (args[i] == arg)
		{
			return funcs[i];
		}
		if (args[i] < arg)
		{
			continue;
		}
		else
		{
			return Interpolation(args[i - 1], args[i], funcs[i - 1], funcs[i], arg);
		}
	}

	// Если дошли до этого места, значит, закончилась последовательность, в пределах которого надо найти интерполированное значение.
	throw new Exception("Закончилась последовательность, в пределах которой надо найти интерполированное значение. Интерполированное значение так и не найдено.");
}
...
Рейтинг: 0 / 0
Оцените подход к линейной интерполяции значения функции
    #38062344
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ещё добавить в начало функции проверку на монотонность входящей последовательности элементов.
...
Рейтинг: 0 / 0
Оцените подход к линейной интерполяции значения функции
    #38062346
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Т. е. входящей последовательности аргументов.
...
Рейтинг: 0 / 0
Оцените подход к линейной интерполяции значения функции
    #38062757
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Достаточно просто сравнивать очередное входящее с текущими максимальным меньшим и минимальным бОльшим аргументами, чем в точке интерполяции - после перебора входной последовательности текущие будут ближайшими.
Если входящая последовательность гарантированно сортирована по аргументу - достаточно сканировать её до изменения знака разности текущей сканируемой точки и точки интерполяции.
...
Рейтинг: 0 / 0
Оцените подход к линейной интерполяции значения функции
    #38063463
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaЕсли входящая последовательность гарантированно сортирована по аргументу - достаточно сканировать её до изменения знака разности текущей сканируемой точки и точки интерполяции.
Да, гарантированно отсортирована по аргументу. Только неизвестно, по возрастанию аргумента или по убыванию - может быть любой порядок.

Также может быть, что значение аргумента текущей точки совпадёт со значением аргумента точки интерполяции - для этого надо отдельное условие (у меня оно есть).

Ещё у вас на каждой итерации две операции - нахождение разности и проверка её знака (я так понимаю, это логическая операция). А у меня только одна логическая.

И не могли бы вы привести ваш алгоритм, я в первой части не понял, что вы имеете ввиду.
...
Рейтинг: 0 / 0
Оцените подход к линейной интерполяции значения функции
    #38063482
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320гарантированно отсортирована по аргументу. Только неизвестно, по возрастанию аргумента или по убыванию - может быть любой порядок.

Также может быть, что значение аргумента текущей точки совпадёт со значением аргумента точки интерполяции - для этого надо отдельное условие (у меня оно есть).

if sign(approx-prev)<>sign(approx-next)

Причёв одно вычитание - реальное, а другое - выполнено на предыдущей итерации.

[quot user7320]AkinaА у меня только одна логическая.
Ага, щазз! одна! а реверс, конечно, выполнится за один процессорный такт...
И поменяй местами If-ы... а то у тебя две логические, а не одна... и, может, даже преобразуй второй if в elseif...
...
Рейтинг: 0 / 0
Оцените подход к линейной интерполяции значения функции
    #38063836
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы уже начали противоречить
user7320Также может быть, что значение аргумента текущей точки совпадёт со значением аргумента точки интерполяцииuser7320на вход подаётся заданное значение аргумента, не совпадающее ни с одним из значений последовательности аргументовВпрочем, это не принципиально (интерполяция на конце отрезка вернёт значение функции на этом конце отрезка), мы только должны быть уверены, что точка интерполяции принадлежит всему интервалу аргументов (аргументов не менее двух). Реверсирование тоже не нужно - мы только должны быть уверены, что значения аргументов монотонно изменяются, кроме того, возможны варианты: например, это может быть очередь данных, и вы их никогда не сможете пресортировать...
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Оцените подход к линейной интерполяции значения функции
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]