c++ 实现线性的曲线拟合扩展

比如 有一组数,和另外一组数,可能长度不一样,但是曲线画出来会非常接近。

那么要比较这两组曲线是否拟合度很高,必须要将其转化为同纬度,即相同的长度,于是产生这样需求。

将一个数组 A[m]扩展成 B[n],使的该曲线线性扩展。

物理解释如下:

原来一张图画在没有拉伸的橡皮纸上,然后把这个图拉伸,用尺子重新量,可以量更多的点,然后记录下来

windows绘图可以展示,如下两图在横轴方向压缩以后必然是重合的。


可能的应用场景:

1.监控某一指标,如测试版本的负载,内存损耗~

上代码:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <string>
#include <map>
#include <iterator>
#include <vector>
#include <time.h>
#include <iostream>

using namespace std;
#define ARY_LEN_A 101
#define ARY_LEN_B 120
int expendArray(float A[], int m, float B[], int n)
{
    int i = 0;  // index for B
    int j = 0;  // index for A in the left of i
    int k = 0;  // index for A in the irhgt of i
    float fdis = 0.0; // the distence from the start point
   
    for(int i=1; i<n-1; i++)
    {
        fdis = 1.0 * (m-1) * i / (n-1);
        j = (int)floor(fdis);
        k = (int)ceil(fdis);
        B[i] = A[j] + (A[k] - A[j]) * (fdis - j*1.0) / (k-j+0.000001);
    }

    B[0] = A[0];
    B[n-1] = A[m-1];
}

/*
-1  :   error
0   :   succ
1   :   fail
*/
int  calcDiffCount(float A[], float B[], int n, float fthreshold)
{
    int nOutFlowCount = 0;
    float fAvgValue = 0;
    for(int i=0; i<n; i++)
    {
        fAvgValue = (A[i] + B[i]) / 2.0;
        if (fAvgValue * (fthreshold + 1.0) > (A[i] > B[i] ? A[i] : B[i]))
        {
            nOutFlowCount++;
        }
    }
    return (nOutFlowCount > n * 0.05 ) ? 0 : 1;
}

/*
-1  :   error
0   :   succ
1   :   fail
*/
int diffByCurveFitting(float A[], int m, float B[], int n, float threshold)
{
    int nRet = 0;
    if (m == n) return calcDiffCount(A, B, m, threshold);
    
    float* pOrig = NULL;
    int nMaxLen = m > n ? m : n;
    float* pExpand = (float*)malloc(sizeof(float*) * nMaxLen);
    if (NULL == pExpand) return -1;
    if (m > n) //keep A
    {
        pOrig = A;
        nMaxLen = m;
        expendArray(B, n, pExpand, m);
    }
    else
    {   //keep B
        pOrig = B;
        nMaxLen = n;
        expendArray(A, m, pExpand, n); 
    }
    nRet = calcDiffCount(pOrig, pExpand, nMaxLen, threshold);

    free(pExpand);
    pExpand = NULL;
    return nRet;
}

int test(float fthreshold)
{
    srand((int)time(0));    
    float fAry[ARY_LEN_A] = {};
    float fBry[ARY_LEN_B] = {};
 
    for(int i=0; i<ARY_LEN_A; i++)
    {
        //srand(i);    
        fAry[i] = 1.0 + 1000.0 * rand() / (RAND_MAX + 1.0);
    } 
    
    expendArray(fAry, ARY_LEN_A, fBry, ARY_LEN_B);
    
    for(int i=0; i<ARY_LEN_B; i++)
    {
        fBry[i] += (0.1 + 10.0 * rand() / (RAND_MAX + 1.0));
    } 

    for(int i=0; i<ARY_LEN_A; i++)
    {
        cout << fAry[i] << "\t" << fBry[i] << endl; 
    }
    for(int i=ARY_LEN_A; i<ARY_LEN_B; i++)
    {
        cout << "xx"  << "\t" << fBry[i] << endl;
    }
    cout << "Result: ";
    cout << diffByCurveFitting(fAry,ARY_LEN_A,fBry,ARY_LEN_B, fthreshold) << endl;
    return 0;
}


int main(int argc, char *argv[])
{
    float fthreshold = atof(argv[1]);
    test(fthreshold);
    return 0;
}

下图为扩展101个点到120个点后的曲线,可以看到基本是拟合的,进一步的研究还未解开

转载于:https://my.oschina.net/sanpeterguo/blog/147294

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当前非线性拟合和多元拟合的工具较少,这是针对常用的拟合算法,开发的一款数据拟合为主的软件。包括线性拟合的各种算法,非线性拟合的各种算法,以及多元拟合的各种算法。其中提供了很多非线性方程的模型,以满足不同的需求,也可以制定自己所需要的指定非线性方程模型的,采用最先进的初始值估算算法,无需初始值就可以拟合自己想要的非线性方程模型各个模块的介绍如下。 1.线性拟合算法模块 根据最小二乘拟合算法,对输入的数据进行变量指定次方的拟合。同时可对自变量或因变量进行自然对数和常用对数的转换后再拟合。根据实际情况,开发了单调性拟合以针对各种定量分析的用途。同时开发了,针对一组数据,得到最高相关系数的自动拟合功能,由程序自动选择拟合次数以及自变量和因变量的数据格式。 2.非线性拟合算法模块 根据非线性方程的特点,开发了最先进的智能初始值估算算法,配合LM迭代算法,进行非线性方程的拟合。只需要输入自变量和因变量,就可以拟合出所需要的非线性方程。拟合相关系数高,方便快捷。并借助微粒群算法,开发了基于微粒群的智能非线性拟合算法,拟合出方程的相关系数相当高,甚至会出现过拟合现象。 3.多元拟合算法模块 根据最小二乘算法的原理开发了多元线性拟合算法,同时开发了能够指定变元次数的高次多元线性拟合。由于多元变量的情况下函数关系复杂,采用高次多元线性拟合能有效提高拟合效果而不会出现过拟合现象。同时针对每个变元可能最合适的拟合次数不一定都一样,开发了自适应高次多元拟合算法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值