Добрый день, коллеги!
Имеется некий датчик (ладно, не некий, а вполне конкретный), чья передаточная характеристика хорошо укладывается в функцию второго порядка, типа y = ax? + bx + c.
В результате калибровки получаем несколько десятков пар значений x и y, по которым нужно найти приближеные коэффициенты a, b и c.
Сейчас, на этапе отладки, решаю это в вольфраме (пример). Но в серии надо будет уметь считать это самому.
Я в математике на уровне чайника, поэтому прошу помочь с алгоритмом или, возможно, с его реализацией.
Заранне благодарен и с уважением, Виктор.
tonyk
21 июл 2021, 11:05
Тут всё на пальцах описано и готовые примеры реализаций. Пользуйся!
drive.google.com/file/d/1RezGyJFUR9PaWUeBkWXVvjS2fZ0BwN37/view?usp=sharing
vix
21 июл 2021, 14:21
tonyk, спасибо за книжку, сохранил.
Нашёл несколько готовых решений. Одно из них переделал на С, выкладываю на всяк. случай, может кому пригодится:
Готовое решение
#include <,stdio.h>,
#include <,stdlib.h>,
#include <,math.h>,
/*
// bragitoff.com/2015/09/c-program-for-polynomial-fit-least-squares/
работает ок
*/
void polinominal_fit
// input
double *x,
double *y,
int N,
// output
double *coeffs,
int n
{
double X2*n+1, //Array that will store the values of sigmaxi,sigmaxi^2,sigmaxi^3….sigmaxi^2n
for int i=0,i<,2*n+1,i++
{
Xi=0,
for int j=0,j<,N,j++
{
Xi=Xi+powxj,i, //consecutive positions of the array will store N,sigmaxi,sigmaxi^2,sigmaxi^3….sigmaxi^2n
}
}
double Bn+1n+2, //B is the Normal matrixaugmented that will store the equations, a is for value of the final coefficients
double *a = coeffs,
for int i=0,i<,=n,i++
{
for int j=0,j<,=n,j++
{
Bij=Xi+j, //Build the Normal matrix by storing the corresponding coefficients at the right positions except the last column of the matrix
}
}
double Yn+1, //Array to store the values of sigmayi,sigmaxi*yi,sigmaxi^2*yi…sigmaxi^n*yi
for int i=0,i<,n+1,i++
{
Yi=0,
for int j=0,j<,N,j++
{
Yi=Yi+powxj,i*yj, //consecutive positions will store sigmayi,sigmaxi*yi,sigmaxi^2*yi…sigmaxi^n*yi
}
}
for int i=0,i<,=n,i++
{
Bin+1=Yi, //load the values of Y as the last column of BNormal Matrix but augmented
}
n=n+1, //n is made n+1 because the Gaussian Elimination part below was for n equations, but here n is the degree of polynomial and for n degree we get n+1 equations
for int i=0,i<,n,i++ //From now Gaussian Elimination startscan be ignored to solve the set of linear equations Pivotisation
{
for int k=i+1,k<,n,k++
{
if Bii<,Bki
{
for int j=0,j<,=n,j++
{
double temp=Bij,
Bij=Bkj,
Bkj=temp,
}
}
}
}
for int i=0,i<,n-1,i++ //loop to perform the gauss elimination
{
for int k=i+1,k<,n,k++
{
double t=Bki/Bii,
for int j=0,j<,=n,j++
{
Bkj=Bkj-t*Bij, //make the elements below the pivot elements equal to zero or elimnate the variables
}
}
}
for int i=n-1,i>,=0,i– //back-substitution
{ //x is an array whose values correspond to the values of x,y,z..
ai=Bin, //make the variable to be calculated equal to the rhs of the last equation
for int j=0,j<,n,j++
{
if j!=i //then subtract all the lhs values except the coefficient of the variable whose value is being calculated
{
ai=ai-Bij*aj,
}
}
ai=ai/Bii, //now finally divide the rhs by the coefficient of the variable to be calculated
}
}
int main
{
double coeffs3,
double x =
{
8764, 8681, 8578, 8403, 8238, 8058, 7921, 7779, 7587, 7481,
7232, 7001, 6924, 6694, 6544, 6364, 6224, 6115, 5625, 5489,
5405, 5156, 5090, 4910, 4775, 4624, 4511
},
double y =
{
138.4299037967, 137.3283395755, 135.4923992069, 132.554894617, 129.9845781009, 127.4142615848,
125.2111331424, 123.7423808475, 120.0705001102, 118.6017478152, 114.9298670779, 111.6251744143,
110.1564221194, 106.8517294558, 104.2814129397, 101.7110964236, 99.1407799075, 97.6720276125,
89.5938899905, 87.7579496218, 87.0235734743, 82.6173165896, 81.5157523684, 78.9454358522,
76.7423074099, 74.1719908937, 72.3360505251
},
polinominal_fitx, y, 27, coeffs, 2,
return 0,
}
Делал библиотечку для наименьших квадратов. Метод более устойчивый и точный чем через нормальные уравнения. Есть пример полиномиальной аппроксимации.
sourceforge.net/p/liblse/code/ci/default/tree/
Viewing 1 reply thread
Вы должны войти в систему, чтобы ответить в этой теме.