26078|22

299

帖子

3804

TA的资源

纯净的硅(初级)

楼主
 

算法——纯C语言最小二乘法曲线拟合 [复制链接]

写完,还没来得及写注释,已通过Matlab的polyfit验证(阶数高或者数据量太大会有double数据溢出的危险,低阶的都吻合),时间有点紧,程序注释,数学推导等时间充裕一点再贴上来
// 最小二乘法拟合.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdlib.h"
#include "math.h"
//
#define ParaBuffer(Buffer,Row,Col) (*(Buffer + (Row) * (SizeSrc + 1) + (Col)))
//
/***********************************************************************************
***********************************************************************************/
static int GetXY(const char* FileName, double* X, double* Y, int* Amount)
{
        FILE* File = fopen(FileName, "r");
        if (!File)
                return -1;
        for (*Amount = 0; !feof(File); X++, Y++, (*Amount)++)
                if (2 != fscanf(File, (const char*)"%lf %lf", X, Y))
                        break;
        fclose(File);
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int PrintPara(double* Para, int SizeSrc)
{
        int i, j;
        for (i = 0; i < SizeSrc; i++)
        {
                for (j = 0; j <= SizeSrc; j++)
                        printf("%10.6lf ", ParaBuffer(Para, i, j));
                printf("\r\n");
        }
        printf("\r\n");
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int ParalimitRow(double* Para, int SizeSrc, int Row)
{
        int i;
        double Max, Min, Temp;
        for (Max = abs(ParaBuffer(Para, Row, 0)), Min = Max, i = SizeSrc; i; i--)
        {
                Temp = abs(ParaBuffer(Para, Row, i));
                if (Max < Temp)
                        Max = Temp;
                if (Min > Temp)
                        Min = Temp;
        }
        Max = (Max + Min) * 0.000005;
        for (i = SizeSrc; i >= 0; i--)
                ParaBuffer(Para, Row, i) /= Max;
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int Paralimit(double* Para, int SizeSrc)
{
        int i;
        for (i = 0; i < SizeSrc; i++)
                if (ParalimitRow(Para, SizeSrc, i))
                        return -1;
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int ParaPreDealA(double* Para, int SizeSrc, int Size)
{
        int i, j;
        for (Size -= 1, i = 0; i < Size; i++)
        {
                for (j = 0; j < Size; j++)
                        ParaBuffer(Para, i, j) = ParaBuffer(Para, i, j) * ParaBuffer(Para, Size, Size) - ParaBuffer(Para, Size, j) * ParaBuffer(Para, i, Size);
                ParaBuffer(Para, i, SizeSrc) = ParaBuffer(Para, i, SizeSrc) * ParaBuffer(Para, Size, Size) - ParaBuffer(Para, Size, SizeSrc) * ParaBuffer(Para, i, Size);
                ParaBuffer(Para, i, Size) = 0;
                ParalimitRow(Para, SizeSrc, i);
        }
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int ParaDealA(double* Para, int SizeSrc)
{
        int i;
        for (i = SizeSrc; i; i--)
                if (ParaPreDealA(Para, SizeSrc, i))
                        return -1;
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int ParaPreDealB(double* Para, int SizeSrc, int OffSet)
{
        int i, j;
        for (i = OffSet + 1; i < SizeSrc; i++)
        {
                for (j = OffSet + 1; j <= i; j++)
                        ParaBuffer(Para, i, j) *= ParaBuffer(Para, OffSet, OffSet);
                ParaBuffer(Para, i, SizeSrc) = ParaBuffer(Para, i, SizeSrc) * ParaBuffer(Para, OffSet, OffSet) - ParaBuffer(Para, i, OffSet) * ParaBuffer(Para, OffSet, SizeSrc);
                ParaBuffer(Para, i, OffSet) = 0;
                ParalimitRow(Para, SizeSrc, i);
        }
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int ParaDealB(double* Para, int SizeSrc)
{
        int i;
        for (i = 0; i < SizeSrc; i++)
                if (ParaPreDealB(Para, SizeSrc, i))
                        return -1;
        for (i = 0; i < SizeSrc; i++)
        {
                if (ParaBuffer(Para, i, i))
                {
                        ParaBuffer(Para, i, SizeSrc) /= ParaBuffer(Para, i, i);
                        ParaBuffer(Para, i, i) = 1.0;
                }
        }
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int ParaDeal(double* Para, int SizeSrc)
{
        PrintPara(Para, SizeSrc);
        Paralimit(Para, SizeSrc);
        PrintPara(Para, SizeSrc);
        if (ParaDealA(Para, SizeSrc))
                return -1;
        PrintPara(Para, SizeSrc);
        if (ParaDealB(Para, SizeSrc))
                return -1;
        return 0;
}
/***********************************************************************************
***********************************************************************************/
static int GetParaBuffer(double* Para, const double* X, const double* Y, int Amount, int SizeSrc)
{
        int i, j;
        for (i = 0; i < SizeSrc; i++)
                for (ParaBuffer(Para, 0, i) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, 0, i) += pow(*(X + j), 2 * (SizeSrc - 1) - i);
        for (i = 1; i < SizeSrc; i++)
                for (ParaBuffer(Para, i, SizeSrc - 1) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, i, SizeSrc - 1) += pow(*(X + j), SizeSrc - 1 - i);
        for (i = 0; i < SizeSrc; i++)
                for (ParaBuffer(Para, i, SizeSrc) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, i, SizeSrc) += (*(Y + j)) * pow(*(X + j), SizeSrc - 1 - i);
        for (i = 1; i < SizeSrc; i++)
                for (j = 0; j < SizeSrc - 1; j++)
                        ParaBuffer(Para, i, j) = ParaBuffer(Para, i - 1, j + 1);
        return 0;
}
/***********************************************************************************
***********************************************************************************/
int Cal(const double* BufferX, const double* BufferY, int Amount, int SizeSrc, double* ParaResK)
{
        double* ParaK = (double*)malloc(SizeSrc * (SizeSrc + 1) * sizeof(double));
        GetParaBuffer(ParaK, BufferX, BufferY, Amount, SizeSrc);
        ParaDeal(ParaK, SizeSrc);
        for (Amount = 0; Amount < SizeSrc; Amount++, ParaResK++)
                *ParaResK = ParaBuffer(ParaK, Amount, SizeSrc);
        free(ParaK);
        return 0;
}
/***********************************************************************************
***********************************************************************************/
int main(int argc, char* argv[])
{
        int Amount;
        double BufferX[1024], BufferY[1024], ParaK[6];
        if (GetXY((const char*)"test.txt", (double*)BufferX, (double*)BufferY, &Amount))
                return 0;
        Cal((const double*)BufferX, (const double*)BufferY, Amount, sizeof(ParaK) / sizeof(double), (double*)ParaK);
        for (Amount = 0; Amount < sizeof(ParaK) / sizeof(double); Amount++)
                printf("ParaK[%d] = %lf!\r\n", Amount, ParaK[Amount]);
        return 0;
}

测试test.txt里的内容
      0.995119      -7.620000
      2.001185      -2.460000
      2.999068     108.760000
      4.001035     625.020000
      4.999859    2170.500000
      6.004461    5814.580000
      6.999335   13191.840000
      7.999433   26622.060000
      9.002257   49230.220000
     10.003888   85066.500000
     11.004076  139226.280000
     12.001602  217970.140000
     13.003390  328843.860000
     14.001623  480798.420000
     15.003034  684310.000000
     16.002561  951499.980000
     17.003010 1296254.940000
     18.003897 1734346.660000
     19.002563 2283552.120000
     20.003530 2963773.500000
matlab拟合m代码:
load test.txt;
x = test(:, 1)';
y = test(:, 2)';
para = polyfit(x, y, 5);

最新回复

mark           详情 回复 发表于 2019-10-28 10:41
点赞 关注(3)
 

回复
举报

299

帖子

3804

TA的资源

纯净的硅(初级)

沙发
 
VC工程文件 最小二乘法拟合.rar (41.19 KB, 下载次数: 230)
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

板凳
 
简单思路如下:
1,采用目标函数对多项式系数求偏导,得到最优值条件,组成一个方程组;
2,方程组的解法采用行列式变换(两次变换:普通行列式——三角行列式——对角行列式——求解),行列式的求解算法上优化过一次了,目前还没有更好的思路再优化运算方法,限幅和精度准备再修改修改
目前存在的问题:
1,代码还是太粗糙
2,数学原理可行,但是计算机运算有幅度溢出和精度问题,这方面欠考虑,导致高阶大数据可能拟合失败
下面附简单注释版代码:
#include "stdafx.h"
#include "stdlib.h"
#include "math.h"

//把二维的数组与一维数组的转换,也可以直接用二维数组,只是我的习惯是不用二维数组
#define ParaBuffer(Buffer,Row,Col) (*(Buffer + (Row) * (SizeSrc + 1) + (Col)))
//

/***********************************************************************************
从txt文件里读取double型的X,Y数据
txt文件里的存储格式为
X1  Y1
X2  Y2
X3  Y3
X4  Y4
X5  Y5
X6  Y6
X7  Y7
X8  Y8
函数返回X,Y,以及数据的数目(以组为单位)
***********************************************************************************/
static int GetXY(const char* FileName, double* X, double* Y, int* Amount)
{
        FILE* File = fopen(FileName, "r");
        if (!File)
                return -1;
        for (*Amount = 0; !feof(File); X++, Y++, (*Amount)++)
                if (2 != fscanf(File, (const char*)"%lf %lf", X, Y))
                        break;
        fclose(File);
        return 0;
}

/***********************************************************************************
打印系数矩阵,只用于调试,不具备运算功能
对于一个N阶拟合,它的系数矩阵大小是(N + 1)行(N + 2)列
double* Para:系数矩阵存储地址
int SizeSrc:系数矩阵大小(SizeSrc)行(SizeSrc + 1)列
***********************************************************************************/
static int PrintPara(double* Para, int SizeSrc)
{
        int i, j;
        for (i = 0; i < SizeSrc; i++)
        {
                for (j = 0; j <= SizeSrc; j++)
                        printf("%10.6lf ", ParaBuffer(Para, i, j));
                printf("\r\n");
        }
        printf("\r\n");
        return 0;
}

/***********************************************************************************
系数矩阵的限幅处理,防止它溢出,目前这个函数很不完善,并不能很好地解决这个问题
原理:矩阵解行列式,同一行乘以一个系数,行列式的解不变
当然,相对溢出问题,还有一个精度问题,也是同样的思路,现在对于这两块的处理很不完善,有待优化
以行为单位处理
***********************************************************************************/
static int ParalimitRow(double* Para, int SizeSrc, int Row)
{
        int i;
        double Max, Min, Temp;
        for (Max = abs(ParaBuffer(Para, Row, 0)), Min = Max, i = SizeSrc; i; i--)
        {
                Temp = abs(ParaBuffer(Para, Row, i));
                if (Max < Temp)
                        Max = Temp;
                if (Min > Temp)
                        Min = Temp;
        }
        Max = (Max + Min) * 0.000005;
        for (i = SizeSrc; i >= 0; i--)
                ParaBuffer(Para, Row, i) /= Max;
        return 0;
}

/***********************************************************************************
同上,以矩阵为单位处理
***********************************************************************************/
static int Paralimit(double* Para, int SizeSrc)
{
        int i;
        for (i = 0; i < SizeSrc; i++)
                if (ParalimitRow(Para, SizeSrc, i))
                        return -1;
        return 0;
}

/***********************************************************************************
系数矩阵行列式变换
***********************************************************************************/
static int ParaPreDealA(double* Para, int SizeSrc, int Size)
{
        int i, j;
        for (Size -= 1, i = 0; i < Size; i++)
        {
                for (j = 0; j < Size; j++)
                        ParaBuffer(Para, i, j) = ParaBuffer(Para, i, j) * ParaBuffer(Para, Size, Size) - ParaBuffer(Para, Size, j) * ParaBuffer(Para, i, Size);
                ParaBuffer(Para, i, SizeSrc) = ParaBuffer(Para, i, SizeSrc) * ParaBuffer(Para, Size, Size) - ParaBuffer(Para, Size, SizeSrc) * ParaBuffer(Para, i, Size);
                ParaBuffer(Para, i, Size) = 0;
                ParalimitRow(Para, SizeSrc, i);
        }
        return 0;
}

/***********************************************************************************
系数矩阵行列式变换,与ParaPreDealA配合
完成第一次变换,变换成三角矩阵
***********************************************************************************/
static int ParaDealA(double* Para, int SizeSrc)
{
        int i;
        for (i = SizeSrc; i; i--)
                if (ParaPreDealA(Para, SizeSrc, i))
                        return -1;
        return 0;
}

/***********************************************************************************
系数矩阵行列式变换
***********************************************************************************/
static int ParaPreDealB(double* Para, int SizeSrc, int OffSet)
{
        int i, j;
        for (i = OffSet + 1; i < SizeSrc; i++)
        {
                for (j = OffSet + 1; j <= i; j++)
                        ParaBuffer(Para, i, j) *= ParaBuffer(Para, OffSet, OffSet);
                ParaBuffer(Para, i, SizeSrc) = ParaBuffer(Para, i, SizeSrc) * ParaBuffer(Para, OffSet, OffSet) - ParaBuffer(Para, i, OffSet) * ParaBuffer(Para, OffSet, SizeSrc);
                ParaBuffer(Para, i, OffSet) = 0;
                ParalimitRow(Para, SizeSrc, i);
        }
        return 0;
}

/***********************************************************************************
系数矩阵行列式变换,与ParaPreDealB配合
完成第一次变换,变换成对角矩阵,变换完毕
***********************************************************************************/
static int ParaDealB(double* Para, int SizeSrc)
{
        int i;
        for (i = 0; i < SizeSrc; i++)
                if (ParaPreDealB(Para, SizeSrc, i))
                        return -1;
        for (i = 0; i < SizeSrc; i++)
        {
                if (ParaBuffer(Para, i, i))
                {
                        ParaBuffer(Para, i, SizeSrc) /= ParaBuffer(Para, i, i);
                        ParaBuffer(Para, i, i) = 1.0;
                }
        }
        return 0;
}

/***********************************************************************************
系数矩阵变换
***********************************************************************************/
static int ParaDeal(double* Para, int SizeSrc)
{
        PrintPara(Para, SizeSrc);
        Paralimit(Para, SizeSrc);
        PrintPara(Para, SizeSrc);
        if (ParaDealA(Para, SizeSrc))
                return -1;
        PrintPara(Para, SizeSrc);
        if (ParaDealB(Para, SizeSrc))
                return -1;
        return 0;
}

/***********************************************************************************
最小二乘法的第一步就是从XY数据里面获取系数矩阵
double* Para:系数矩阵地址
const double* X:X数据地址
const double* Y:Y数据地址
int Amount:XY数据组数
int SizeSrc:系数矩阵大小(SizeSrc)行(SizeSrc + 1)列
***********************************************************************************/
static int GetParaBuffer(double* Para, const double* X, const double* Y, int Amount, int SizeSrc)
{
        int i, j;
        for (i = 0; i < SizeSrc; i++)
                for (ParaBuffer(Para, 0, i) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, 0, i) += pow(*(X + j), 2 * (SizeSrc - 1) - i);
        for (i = 1; i < SizeSrc; i++)
                for (ParaBuffer(Para, i, SizeSrc - 1) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, i, SizeSrc - 1) += pow(*(X + j), SizeSrc - 1 - i);
        for (i = 0; i < SizeSrc; i++)
                for (ParaBuffer(Para, i, SizeSrc) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, i, SizeSrc) += (*(Y + j)) * pow(*(X + j), SizeSrc - 1 - i);
        for (i = 1; i < SizeSrc; i++)
                for (j = 0; j < SizeSrc - 1; j++)
                        ParaBuffer(Para, i, j) = ParaBuffer(Para, i - 1, j + 1);
        return 0;
}

/***********************************************************************************
整个计算过程
***********************************************************************************/
int Cal(const double* BufferX, const double* BufferY, int Amount, int SizeSrc, double* ParaResK)
{
        double* ParaK = (double*)malloc(SizeSrc * (SizeSrc + 1) * sizeof(double));
        GetParaBuffer(ParaK, BufferX, BufferY, Amount, SizeSrc);
        ParaDeal(ParaK, SizeSrc);
        for (Amount = 0; Amount < SizeSrc; Amount++, ParaResK++)
                *ParaResK = ParaBuffer(ParaK, Amount, SizeSrc);
        free(ParaK);
        return 0;
}

/***********************************************************************************
测试main函数
数据组数:20
阶数:5
***********************************************************************************/
int main(int argc, char* argv[])
{
        //数据组数
        int Amount;
        //XY缓存,系数矩阵缓存
        double BufferX[1024], BufferY[1024], ParaK[6];
        if (GetXY((const char*)"test.txt", (double*)BufferX, (double*)BufferY, &Amount))
                return 0;
        //运算
        Cal((const double*)BufferX, (const double*)BufferY, Amount, sizeof(ParaK) / sizeof(double), (double*)ParaK);
        //输出系数
        for (Amount = 0; Amount < sizeof(ParaK) / sizeof(double); Amount++)
                printf("ParaK[%d] = %lf!\r\n", Amount, ParaK[Amount]);
        //屏幕暂留
        system("pause");
        return 0;
}
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

4
 
手写了一个简单数学推导(以二阶为例) pic.rar (742.91 KB, 下载次数: 155)
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

5
 
系数矩阵很容易看规律来,高阶的也符合这个规律,然后写一个通用的行列式的解法,问题就OK了一半
行列变换的顺序按照图中给出的顺序可以很方便地设计出运算量比较小的高阶行列式变换矩阵算法(类似迭代),上文中的几个Deal函数就是这个思路
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

6
 
数学上理解不难,时基实施会有很大问题,主要是数据精度,数据的溢出问题
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

7
 
程序中设计有类似增益调节的函数(Paralimit),可以部分的解决一些问题,但是目前没有很完美的思路,所以高阶,多数据,大数据慎用此程序
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

8
 
程序的调试思路也比较简单,一步步跟踪系数矩阵的变换,每次变换后输出系数矩阵,看看问题在哪,就知道有哪些地方不完善了
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

9
 
矩阵变换思路:
普通矩阵——下三角矩阵——对角矩阵,之所以这么设计,考虑到高阶采用嵌套和迭代
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

10
 
二阶的系数矩阵方程组:
(目标函数y = A * x^2 + b * x^1 + C *x^0)
注意!
(X^N表示的是X1^N + X2^N + X3^N + X4^N + …… + Xn^N)
(Y * X^N表示的是Y1 * X1^N + Y1 * X2^N + Y3 * X3^N + Y4 * X4^N + …… + Yn * Xn^N)
X^4 * A + X^3 * B + X^2 * C = Y * X ^2
X^3 * A + X^2 * B + X^1 * C = Y * X ^1
X^2 * A + X^1 * B + X^0 * C = Y * X ^0

三阶的系数矩阵方程组:
注意!
(X^N表示的是X1^N + X2^N + X3^N + X4^N + …… + Xn^N)
(Y * X^N表示的是Y1 * X1^N + Y1 * X2^N + Y3 * X3^N + Y4 * X4^N + …… + Yn * Xn^N)
(目标函数y = A * x^3 + b * x^2 + C *x^1 + D * x^0)
X^6 * A + X^5 * B + X^4 * C + X^3 * D = Y * X ^3
X^5 * A + X^4 * B + X^3 * C + X^2 * D = Y * X ^2
X^4 * A + X^3 * B + X^2 * C + X^1 * D = Y * X ^1
X^3 * A + X^2 * B + X^1 * C + X^0 * D = Y * X ^0

更高阶的规律也跟上面一样,所以第一步就是获取系数矩阵,需要算的值有X^0, X^1, …… X^(2N), Y * X^0, Y * X^1,……Y* X^N,N表示阶数
在本程序中用如下代码实现:
/***********************************************************************************
最小二乘法的第一步就是从XY数据里面获取系数矩阵
double* Para:系数矩阵地址
const double* X:X数据地址
const double* Y:Y数据地址
int Amount:XY数据组数
int SizeSrc:系数矩阵大小(SizeSrc)行(SizeSrc + 1)列
***********************************************************************************/
static int GetParaBuffer(double* Para, const double* X, const double* Y, int Amount, int SizeSrc)
{
        int i, j;
//先把第0行的搞定
        for (i = 0; i < SizeSrc; i++)
                for (ParaBuffer(Para, 0, i) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, 0, i) += pow(*(X + j), 2 * (SizeSrc - 1) - i);
//把第(SizeSrc - 1)列的搞定
        for (i = 1; i < SizeSrc; i++)
                for (ParaBuffer(Para, i, SizeSrc - 1) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, i, SizeSrc - 1) += pow(*(X + j), SizeSrc - 1 - i);
//把第(SizeSrc)列的搞定
        for (i = 0; i < SizeSrc; i++)
                for (ParaBuffer(Para, i, SizeSrc) = 0, j = 0; j < Amount; j++)
                        ParaBuffer(Para, i, SizeSrc) += (*(Y + j)) * pow(*(X + j), SizeSrc - 1 - i);
//剩下的全是拷贝,不存在复杂计算了,省了很多事
        for (i = 1; i < SizeSrc; i++)
                for (j = 0; j < SizeSrc - 1; j++)
                        ParaBuffer(Para, i, j) = ParaBuffer(Para, i - 1, j + 1);
        return 0;
}
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

11
 
推导残差方程——对残差方程偏导——求出系数矩阵——解系数矩阵——OK了,残差方程的推导以二阶为例(有耐心的话三阶也能,更高阶的推导换思路),再找出矩阵规律(有点投机取巧了,要是有耐心,还可以证明一下,不过貌似不简单)
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

12
 
解系数矩阵的算法:行变换
1,矩阵变换有个特点,尽可能快地变换出更多的0,而且0的位置最好有规律,因为可以在写循环的时候直接PASS掉,省掉很多浮点运算,快速性变好
2,高阶运算的计算步骤很多,最好是实现迭代或者递推,这样写代码轻松很多
3,矩阵系数中可能本来就含有0,因此慎用除法,当然用乘法也有一个严重的问题,很容易溢出(这一条现在很不严谨,可能有疏漏谬误)
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

13
 
以三阶为例,行变换顺序:
K00   K01   K02   K03   K04
K10   K11   K12   K13   K14
K20   K21   K22   K23   K24
K30   K31   K32   K33   K34
利用第3行消去第0,1,2行的第3列
K00   K01   K02   000   K04
K10   K11   K12   000   K14
K20   K21   K22   000   K24
K30   K31   K32   K33   K34
利用第2行消去第0,1行的第2列
K00   K01   000   000   K04
K10   K11   000   000   K14
K20   K21   K22   000   K24
K30   K31   K32   K33   K34
利用第1行消去第0行的第1列
K00   000   000   000   K04
K10   K11   000   000   K14
K20   K21   K22   000   K24
K30   K31   K32   K33   K34
上面的三个步骤用的函数,运用了递推的算法
/***********************************************************************************
系数矩阵行列式变换
***********************************************************************************/
static int ParaPreDealA(double* Para, int SizeSrc, int Size)
{
        int i, j;
        for (Size -= 1, i = 0; i < Size; i++)
        {
                for (j = 0; j < Size; j++)
                        ParaBuffer(Para, i, j) = ParaBuffer(Para, i, j) * ParaBuffer(Para, Size, Size) - ParaBuffer(Para, Size, j) * ParaBuffer(Para, i, Size);
                ParaBuffer(Para, i, SizeSrc) = ParaBuffer(Para, i, SizeSrc) * ParaBuffer(Para, Size, Size) - ParaBuffer(Para, Size, SizeSrc) * ParaBuffer(Para, i, Size);
                ParaBuffer(Para, i, Size) = 0;
                ParalimitRow(Para, SizeSrc, i);
        }
        return 0;
}

/***********************************************************************************
系数矩阵行列式变换,与ParaPreDealA配合
完成第一次变换,变换成三角矩阵
***********************************************************************************/
static int ParaDealA(double* Para, int SizeSrc)
{
        int i;
        for (i = SizeSrc; i; i--)
                if (ParaPreDealA(Para, SizeSrc, i))
                        return -1;
        return 0;
}
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

14
 
K00   000   000   000   K04
K10   K11   000   000   K14
K20   K21   K22   000   K24
K30   K31   K32   K33   K34
用第0行消去第1,2,3行
K00   000   000   000   K04
000   K11   000   000   K14
000   K21   K22   000   K24
000   K31   K32   K33   K34
用第1行消去第2,3行
K00   000   000   000   K04
000   K11   000   000   K14
000   000   K22   000   K24
000   000   K32   K33   K34
用第2行消去第3行
K00   000   000   000   K04
000   K11   000   000   K14
000   000   K22   000   K24
000   000   000   K33   K34
这个操作用的函数如下,也运用了递推
/***********************************************************************************
系数矩阵行列式变换
***********************************************************************************/
static int ParaPreDealB(double* Para, int SizeSrc, int OffSet)
{
        int i, j;
        for (i = OffSet + 1; i < SizeSrc; i++)
        {
                for (j = OffSet + 1; j <= i; j++)
                        ParaBuffer(Para, i, j) *= ParaBuffer(Para, OffSet, OffSet);
                ParaBuffer(Para, i, SizeSrc) = ParaBuffer(Para, i, SizeSrc) * ParaBuffer(Para, OffSet, OffSet) - ParaBuffer(Para, i, OffSet) * ParaBuffer(Para, OffSet, SizeSrc);
                ParaBuffer(Para, i, OffSet) = 0;
                ParalimitRow(Para, SizeSrc, i);
        }
        return 0;
}

/***********************************************************************************
系数矩阵行列式变换,与ParaPreDealB配合
完成第一次变换,变换成对角矩阵,变换完毕
***********************************************************************************/
static int ParaDealB(double* Para, int SizeSrc)
{
        int i;
        for (i = 0; i < SizeSrc; i++)
                if (ParaPreDealB(Para, SizeSrc, i))
                        return -1;
        for (i = 0; i < SizeSrc; i++)
        {
                if (ParaBuffer(Para, i, i))
                {
                        ParaBuffer(Para, i, SizeSrc) /= ParaBuffer(Para, i, i);
                        ParaBuffer(Para, i, i) = 1.0;
                }
        }
        return 0;
}
 
 
 

回复

299

帖子

3804

TA的资源

纯净的硅(初级)

15
 
至此,这个三阶拟合的推导已经结束
 
 
 

回复

132

帖子

0

TA的资源

一粒金砂(中级)

16
 
谢谢咯
 
 
 

回复

973

帖子

15

TA的资源

纯净的硅(高级)

17
 
很好啊,谢谢楼主,记下学习了
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

18
 
谢谢分享,正需要
 
 
 

回复

8

帖子

2

TA的资源

一粒金砂(初级)

19
 
楼主威武
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

20
 
mark
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

猜你喜欢
随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条
ADI &文晔 探索季第一站,邀您在活动帖跟帖,ADI资深工程师将与您一道寻求解决之道! ...
春晚,最出圈当属穿着棉马甲跳秧歌的机器人”秧Bot”。
转手绢、飞手绢、变换队形,精准度和稳定性甚至超越人类,这背后少不了电机控制技术。

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表