Помощь - Поиск - Пользователи - Календарь
Полная версия: Помогите пожалуйста решить задачу аппроксимации
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
neo123
Здравствуйте!
Помогите решить задачку.
Что то мой уже не молодой мозг, знакомый и с пасклем и с делфи и с численным моделированием, и с численными решениями дает сбои.
Чувствую что вопрос какой то у меня слишком примитивный.
Вообщем подскажите как сделать элементарную аппрокисацию. Линейную я так понимаю.
Вот есть массив а(1...8) численных значений (не целых, тип реал). Например 20, 100, 150.....
Ему соответствует массив b(1...8) численных значений (не целых, тип реал). 100, 200, 300.....
И допустим, мы вводим значение ai=40, и нужно методом аппрокимации определить, какое значение из массива b ему соответствует.
Т.е., в уме рассчитаем:
a3=(a1+a2)/2=(20+100)/2=60 ему соответсвует: b3=( b1+b2)/2 = 100+200 / 2 = 150
a4=(a1+a3)/2=(20+60)/2=40 ему соответсвует: b4=(b1+b3)/2 = 100+150 / 2 = 125.

Результат: ai=40 соответствует b4=125

Подскажите как запрограммировать, ну или хоть какой это численный метод....
Спасибо...

Федосеев Павел
Метод - кусочно-линейная аппроксимация.

Алгоритм такой-же как и на словах.
1. Перебор i от 2 до 7 (при диапазоне 1...8) и поиск a[i]<ai
2. Если найден, то запоминаем i и считаем пропорцию диапазона (i-1) - (i)
3. Если не найден, то считаем пропорцию из последнего диапазона (7) - (8)
4. Всё.
neo123
Спасибо большое!!!
Только у меня какие то сомнения что это такой метод, поскольку мы имеем не функцию, а набор каких то чисел в диапазоне.
Вот данные:

const a: array[1..8] of integer =(250,230,224,223,197,173,167,164);
b: array[1..8] of integer = (460,435,460,505,510,520,480,450);
T: array[1..8] of integer = (20,100,150,200,250,300,350,375);

Например, нужно определить значение a и b для T=140.

Я что то голову уже сломал, не получается, вот код:

T1:=StrToInt(edit4.text); {T1=140}

for i:=2 to 8 do
begin
if T[i]<T1 then
begin
Tk:=RoundTo((T[i]+T[i+1])/2, 1);
ak:=RoundTo((a[i]+a[i+1])/2, 1);
bk:=RoundTo((b[i]+b[i+1])/2, 1);


Repeat
begin
if Tk<T1 then begin
Tk:=RoundTo((Tk+T[i+1])/2, 1);
ak:=RoundTo((ak+a[i+1])/2, 1);
bk:=RoundTo((bk+b[i+1])/2, 1);
end;
if Tk>T1 then begin
Tk:=RoundTo((Tk+T[i])/2, 1);
ak:=RoundTo((ak+a[i+1])/2, 1);
bk:=RoundTo((bk+b[i+1])/2, 1);
end;
end;
Until Tk=T1;
end;
end;

Подскажите пожалуйста, что не так...
Федосеев Павел
Offtop. При вставке кода программы пользуемся кнопкой CODE и закрываем тег кнопкой #.
Набираем "кусочно-линейная интерполяция" - получаем в частности хабр, вики, Розетта и многое другое.

У меня FreePascal, поэтому, возможны несоответствия в синтаксисе, но алгоитм описан выше

{
Кусочно-линейная интерполяция.
}

program LinearInterpoltion;

const
a: array[1..8] of real = (250, 230, 224, 223, 197, 173, 167, 164);
b: array[1..8] of real = (460, 435, 460, 505, 510, 520, 480, 450);
T: array[1..8] of real = (20, 100, 150, 200, 250, 300, 350, 375);

function LinInterp(x0: real; var x, y: array of real): real;
var
i: integer;
begin
for i := low(x) + 1 to high(x) do
begin
if (x0 <= x[i]) or (i = high(x)) then
begin
LinInterp := y[i - 1] + (y[i] - y[i - 1]) * (x0 - x[i - 1]) / (x[i] - x[i - 1]);
break;
end;
end;
end;

begin
writeln(LinInterp(15, T, a): 6: 1);
writeln(LinInterp(150, T, a): 6: 1);
writeln(LinInterp(140, T, a): 6: 1);
writeln(LinInterp(380, T, a): 6: 1);
end.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.