插值方法

这篇博客分享了作者在学习计算方法课程中的实验经历,重点探讨了三种插值方法——分段插值、拉格朗日插值和牛顿插值。作者通过实验代码记录了这些方法,并指出拉格朗日插值和分段插值采用了链表数据结构,而牛顿插值使用数组更为合适。实验代码仅作参考,但强调插值方法在提高图像分辨率等领域的应用价值。

一、写在前面
自打学习了计算方法这门课程,深刻的把数学与编程再与实际结合在一起,深深的感受到了数值分析的魅力,以及数学的奥妙,233333,数学太强大了,不啰嗦了,进入正题。
1、一下代码仅供参考,我只是把我实验的代码拿来记录下来,本次实验涉及到三种插值方法:分段插值、拉格朗日插值、牛顿插值。
2、实验题目:
根据实际,写自己的代码
3、请各位客官加以理解后,自行改写自己的代码

二、实验结果
这里写图片描述

#include <stdio.h>

typedef struct Node{    //将结点写成结构的形式
    float x;
    float y;
    struct Node *next;
}Node;

typedef struct Data{
    float x;
    float y;
}Data;

float LagrangeInsert(Node* head, float x)
{
    Node *point1, *point2, *p;
    float temp1, temp2;

    point1 = point2 = head->next;
    temp1 = 0;                //记录内循环的积
    temp2 = 1;                //记录外循环的和
    while(NULL != point1)
    {
        while(NULL != point2)
        {
            if(point1 != point2)
                temp2 *= (x - point2->x) / (point1->x - point2->x);   //temp2表示L(x)
            point2 = point2->next;
        }
        temp1 += temp2*point1->y;
        temp2 = 1;
        point2 = head->next;
        point1 = point1->next;
    }
    return temp1;
}

float PiecewiseLinearInsert(Node* head, float x)
{
    head = head->next;    //跳过头结点
    Node *point;
    float temp;
    float pace = (head->next->x) - (head->x);    //步长

    point = head;
    while((x - point->x) > pace)    //确定区间
        point = point->next;
    temp = (point->y)*(x-(point->next->x))/(point->x - point->next->x);
    temp += (point->next->y)*(x-(point->x))/(point->next->x - point->x);
    return temp;
}

float DifferenceQuotient(Data* point, int start, int end)   //递归的方法求差商
{
    if(start == end)
        return point[start].y;
    return (DifferenceQuotient(point, start+1, end)-DifferenceQuotient \
            (point, start, end-1))/(point[end].x - point[start].x);
}

float NewtonInsert(Data* point, float x, int nodeNum)
{
    int flag = 0, i = 0;
    float answer = 0.0;
    float temp, chaShang;
    while(flag <= nodeNum-1)
    {
        chaShang = DifferenceQuotient(point, 0, flag);
        for(i=0; i<flag; i++)
        {
            chaShang *= (x-point[i].x);   //此时已不是差商,而是一项
        }
        answer += chaShang;
        flag++;
    }

    return answer;
}

float function(float x)    //原函数
{
    return 1/(1 + x*x);
}

void main()
{

    /* 实验一 */
    int j;
    float i;
    float cin;
    float F, L, P;
    Node* newNode = malloc(sizeof(Node));
    Node* head = newNode;
    head->next = NULL;
    for(i=-5.0; i<6; i++)    //尾插法建立有头结点链表x(i):-5.0 -4.0 .... 5.0
    {
        Node* temp = malloc(sizeof(Node));
        temp->x = i;
        temp->y = function(i);
        temp->next = NULL;
        newNode->next = temp;
        newNode = temp;
    }
    printf("---------------------------实验一--------------------------\n");
    printf("请输入插值x:");
    scanf("%f", &cin);
    F = function(cin);
    L = LagrangeInsert(head, cin);
    P = PiecewiseLinearInsert(head, cin);
    printf("X         y(精确)     y(拉格朗日)y(分段线性)  误差(拉)  误差(分)\n");
    printf("%f  %f    %f   %f    %f    %f\n", cin, F, L, P, F-L, F-P);

    printf("请输入插值x:");
    scanf("%f", &cin);

    F = function(cin);
    L = LagrangeInsert(head, cin);
    P = PiecewiseLinearInsert(head, cin);
    printf("X         y(精确)     y(拉格朗日)y(分段线性)  误差(拉)  误差(分)\n");
    printf("%f  %f    %f   %f    %f    %f\n", cin, F, L, P, F-L, F-P);

    /* 实验二 */
    printf("\n\n--------------------------实验二-------------------------\n");
    Data array[100];   //可存放100个结点数据
    int nodeNum = 3;
    i = 1.0;           //y0 = 1.0
    for(j=0; j<nodeNum; j++)    //建立节点信息数组
    {
        array[j].y = i;
        array[j].x = i*i;
        i++;
    }
    printf("Answer: %f", NewtonInsert(array, 5.0, 3));
}

三、写在后面
1、三种插值方法的思想是根据公式得来的,其中拉格朗日插值、分段插值我用的是链表作为数据链,但是牛顿插值的话,还是用数组好。关于这一点我得自我批评下,本来三种方法都可以用数组存储结点数据的,用链表反而感觉不方便了,这是我写到牛顿插值才发现的问题,之前也就懒得改的。
2、代码仅供参考,因为是要上交的实验代码,并没有用心去维护,思想可以借鉴。
3、插值方法的应用:越来越多的领域需要高分辨率图像,采用图像插值技术来提高数字图像的分辨率和清晰度,从软件方面进行改进就具有十分重要的实用价值。图像插值是一个数据再生过程。由原始图像数据再生出具有更高分辨率的图像数据。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值