一、写在前面
自打学习了计算方法这门课程,深刻的把数学与编程再与实际结合在一起,深深的感受到了数值分析的魅力,以及数学的奥妙,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、插值方法的应用:越来越多的领域需要高分辨率图像,采用图像插值技术来提高数字图像的分辨率和清晰度,从软件方面进行改进就具有十分重要的实用价值。图像插值是一个数据再生过程。由原始图像数据再生出具有更高分辨率的图像数据。
这篇博客分享了作者在学习计算方法课程中的实验经历,重点探讨了三种插值方法——分段插值、拉格朗日插值和牛顿插值。作者通过实验代码记录了这些方法,并指出拉格朗日插值和分段插值采用了链表数据结构,而牛顿插值使用数组更为合适。实验代码仅作参考,但强调插值方法在提高图像分辨率等领域的应用价值。
559

被折叠的 条评论
为什么被折叠?



