发新帖我要提问
12
返回列表
打印
[技术讨论]

外推算法的数学问题

[复制链接]
楼主: kktron
手机看帖
扫描二维码
随时随地手机跟帖
21
xch| | 2021-12-4 20:09 | 只看该作者 回帖奖励 |倒序浏览
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
float lagrange( float x);
long double cc[25][2]={\
2479.8     ,           200,
2538.6     ,           190,
2598.8      ,          180,
2663.3       ,         170,
2726.2      ,          160,
2790.8      ,          150,
2857.3      ,          140,
2928.2      ,          130,
2998.7      ,          120,
3071.8     ,           110,
3145.4     ,           100,
3221.3     ,           90,
3301.5     ,           80,
3381.5     ,            70,
3463       ,            60,
3549.6     ,           50,
3632.6     ,           40,
3722.7     ,           30,
3815.5     ,            20,
3903       ,           10,
3996.9     ,             0,
4091.1      ,          -10,
4190.8      ,          -20,
4287.6      ,          -30,
4383.4      ,          -40,
};

int main()
{


   printf("y= %f \n",lagrange(4383.50));
printf("y= %f \n",lagrange(5001.23));
printf("y= %f \n",lagrange(1234.56 ));
printf("y= %f \n",lagrange(3904 ));
    return 0;

};

float lagrange( float x)
{
        int i,j;
         long double result = 0.0,k=1.0;
         int m,n;
         if (x>= cc[22][0])
         {

             m = 25;
             n= 22;
         }
         else if (x<=cc[2][0])
         {

                m = 3;
                n = 0;
         }
         else
         {
             n=2;
             while (x>cc[n][0]){
                    n++;
             }
             n= n-1;
             m= n+3;

        }

        for(i=n;i<m;i++)
        {
                k=1.0;
                for(j=n;j<m;j++)
                {
                       if(j!=i)
                        {

                            k=k*(x-cc[j][0])/(cc[i][0]-cc[j][0]);
                        }



                }
                result =result+cc[i][1]*k;
        }
        return result;
}
;;

使用特权

评论回复
22
xch| | 2021-12-4 20:10 | 只看该作者
运行结果

使用特权

评论回复
23
kktron|  楼主 | 2021-12-4 21:33 | 只看该作者

谢谢!我来试试看效果

使用特权

评论回复
24
kktron|  楼主 | 2021-12-4 22:12 | 只看该作者

试了下,还是不对的。
开始X输入最大值大一点的X输出还是对的
后面输入值 X越大,Y反而变大了。和最小二乘法的问题基本一样

使用特权

评论回复
25
xch| | 2021-12-4 23:37 | 只看该作者
kktron 发表于 2021-12-4 22:12
试了下,还是不对的。
开始X输入最大值大一点的X输出还是对的
后面输入值 X越大,Y反而变大了。和最小二 ...

那就只能用折线插值。也是拉格朗日插值特例。我等下试试大x值

使用特权

评论回复
26
xch| | 2021-12-4 23:43 | 只看该作者
输入6000.没问题

使用特权

评论回复
27
xch| | 2021-12-4 23:45 | 只看该作者
12000输入也没问题

使用特权

评论回复
28
xch| | 2021-12-4 23:47 | 只看该作者
输入负数,较小值也正常

使用特权

评论回复
29
xch| | 2021-12-4 23:50 | 只看该作者
Lagrange.zip (23.05 KB)


使用特权

评论回复
30
kktron|  楼主 | 2021-12-5 00:58 | 只看该作者

输入5000,6000,7000等 会发现值一会变小一会变大

使用特权

评论回复
31
eon_xyz| | 2021-12-5 09:17 | 只看该作者
分段拟合

使用特权

评论回复
32
zzz3265| | 2021-12-5 16:51 | 只看该作者
参数拟合适用性较好的一般用4参数方程,  拟合方程式:Y = (A - D) / [1 + (X/C)B] + D
你这个数据简单点可以试试 y = (a*x+b)/(c*x+1)       f(4385)=-40.1586
或者  y = a*x+b*log(x)+c/x+d              f(4385)=-40.1539                       

使用特权

评论回复
33
jrcsh| | 2021-12-6 00:03 | 只看该作者
把没作的数据补上正确的值  重新生成  拟合公式~~   完  

使用特权

评论回复
34
csdnpurple| | 2021-12-6 11:26 | 只看该作者
jrcsh 发表于 2021-12-6 00:03
把没作的数据补上正确的值  重新生成  拟合公式~~   完

有重要信息的数据不用,太浪费

使用特权

评论回复
35
jrcsh| | 2021-12-8 04:19 | 只看该作者
csdnpurple 发表于 2021-12-6 11:26
有重要信息的数据不用,太浪费

他的解题思路对数据准确性控制不好, 既然有限的数据去求不确定的数据偏差这么大,  干脆把未知的数据标定出来成为准确的数据,重新生成准确的拟合公式即可,   解题不要限死于给定条件。

使用特权

评论回复
36
kktron|  楼主 | 2021-12-8 12:29 | 只看该作者
jrcsh 发表于 2021-12-8 04:19
他的解题思路对数据准确性控制不好, 既然有限的数据去求不确定的数据偏差这么大,  干脆把未知的数据标定 ...

实际应用时标定的只有几组。不是全程的

假如全段数据可用,那用切比雪夫,拉格朗日,或者最小二乘法,再简单点的线性内插法(这些我都一一试过验证了)
都可以得到满足的要求,也就不存在 外推的问题了。

目前拉格朗日法 外推 用的29楼xch的代码,基本满足,
但是MDK可能编译环境问题,x=6200多后会y出现最小值了,x再变大
y反而变回大值的趋势,这部分好几天没搞定。 和xch的验证不一致
y高于200部分,倒是没问题都按外推法曲线满足的。

使用特权

评论回复
37
jrcsh| | 2021-12-9 23:52 | 只看该作者
kktron 发表于 2021-12-8 12:29
实际应用时标定的只有几组。不是全程的

假如全段数据可用,那用切比雪夫,拉格朗日,或者最小二乘法,再 ...

你这个解法  可以看出,趋势不对,  我建议还是先作已经理论值标定.   至于编译器器,看看别人的什么好的处理方法, 或者在 x86上试试  6200 这么小的数  怎么样就会出错, 全部给他们上 4字节变量谁怕谁

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则