?? lagrange.cpp
字號:
//////////////////////////////////////////////
// §2 插值方法
//
// 程序2.1 — Lagrange 插值
////////////////////////////////////////////////////////////////////////
//
//本程序最后將顯示函數(shù)表和插值函數(shù)圖形曲線,是TC版本,必須用TC,BC編譯.
//如果對Visual C/C++的Windows程序有興趣,請發(fā)e-mail索取,其中包括了所有
//其中包括了所有插值和曲線擬合等功能強大的程序
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <graphics.h>
#include <math.h>
//點結(jié)構定義
typedef struct {
float x;
float y;
} POINT;
//插值函數(shù)原型
float Lagrange(POINT Table[],int n,float x);
//圖形初始化
void InitGraph()
{
int gdriver = DETECT, gmode;
initgraph(&gdriver, &gmode, "");
}
//畫線
void line(int x1,int y1,int x2,int y2,int color)
{
setcolor(color);
line(x1,y1,x2,y2);
}
//字符串顯示
void outtextxy(int x,int y,char text[],int color)
{
setcolor(color);
outtextxy(x,y,text);
}
//實數(shù)顯示
void outtextxy(int x,int y,float RealNumber,int Length,int color)
{
char String[20];
setcolor(color);
gcvt(RealNumber,Length,String);//實數(shù)轉(zhuǎn)換為字符串
outtextxy(x,y,String);
}
//表格線顯示
void ShowTable(POINT Table[],int n)
{
int i;
char String_x[20],String_y[20];
line(0,20,639,20,7);
line(30,0,30,40);
outtextxy(10,8,"x",14);
outtextxy(10,28,"y",14);
for(i=0;i<n;++i)
{
outtextxy(36+i*80,8,Table[i].x,6,14);
outtextxy(36+i*80,28,Table[i].y,6,14);
}
}
//得到函數(shù)表中x值的絕對值最大值,用來計算坐標的刻度單位
float GetMaximum_x(POINT Table[],int n)
{
int i;
int Max_x;
Max_x=0.0;
for(i=0;i<n;++i)
if(Max_x<fabs(Table[i].x)) Max_x=fabs(Table[i].x);
return(Max_x);
}
//得到函數(shù)表中y值的絕對值最大值,用來計算坐標的刻度單位
float GetMaximum_y(POINT Table[],int n)
{
int i;
int Max_y;
Max_y=0.0;
for(i=0;i<n;++i)
if(Max_y<fabs(Table[i].y)) Max_y=fabs(Table[i].y);
return(Max_y);
}
//畫直角坐標
void DrawCoordinate(int X1,int Y1,int X2,int Y2,
float x1,float y1,float x2,float y2)
{
char String[20];
line(X1,(Y1+Y2)/2,X2,(Y1+Y2)/2,7);
line(X2,(Y1+Y2)/2,X2-10,(Y1+Y2)/2-2);
line(X2,(Y1+Y2)/2,X2-10,(Y1+Y2)/2+2);
line((X1+X2)/2,Y1,(X1+X2)/2,Y2);
line((X1+X2)/2,Y1,(X1+X2)/2-2,Y1+10);
line((X1+X2)/2,Y1,(X1+X2)/2+2,Y1+10);
line((X1+X2)/2+(X2-X1)/4,(Y1+Y2)/2-4,
(X1+X2)/2+(X2-X1)/4,(Y1+Y2)/2);
gcvt((x1+x2)/2+(x2-x1)/4,6,String);
outtextxy((X1+X2)/2+(X2-X1)/4-3,(Y1+Y2)/2+4,String);
line((X1+X2)/2-(X2-X1)/4,(Y1+Y2)/2-4,
(X1+X2)/2-(X2-X1)/4,(Y1+Y2)/2);
gcvt(-((x1+x2)/2+(x2-x1)/4),6,String);
outtextxy((X1+X2)/2-(X2-X1)/4-3,(Y1+Y2)/2+4,String);
line((X1+X2)/2+4,(Y1+Y2)/2-(Y2-Y1)/4,
(X1+X2)/2,(Y1+Y2)/2-(Y2-Y1)/4);
gcvt(-((y1+y2)/2+(y2-y1)/4),6,String);
outtextxy((X1+X2)/2+8,(Y1+Y2)/2-(Y2-Y1)/4-2,String);
line((X1+X2)/2+4,(Y1+Y2)/2+(Y2-Y1)/4,
(X1+X2)/2,(Y1+Y2)/2+(Y2-Y1)/4);
gcvt(((y1+y2)/2+(y2-y1)/4),6,String);
outtextxy((X1+X2)/2+8,(Y1+Y2)/2+(Y2-Y1)/4-2,String);
}
//實坐標中實數(shù)x轉(zhuǎn)換到窗口坐標的值
int xToX(int X1,int X2,float x1,float x2,float x)
{
return((int)(X1+(X2-X1)*(x-x1)/(x2-x1)));
}
//實坐標中實數(shù)y轉(zhuǎn)換到窗口坐標的值
int yToY(int Y1,int Y2,float y1,float y2,float y)
{
return((int)(Y1+(Y2-Y1)*(y-y1)/(y2-y1)));
}
//畫插值函數(shù)曲線
void DrawFunctionCurve(int X1,int Y1,int X2,int Y2,
float x1,float y1,float x2,float y2,
POINT Table[],int n)
{
int i;
float Real_x_step;
if(X2<=X1) {printf("error screen window!");return;}
Real_x_step=(x2-x1)/(X2-X1);
for(i=0;i<X2-X1;++i)
line(xToX(X1,X2,x1,x2,x1+i*Real_x_step),
yToY(Y1,Y2,y1,y2,Lagrange(Table,n,x1+i*Real_x_step)),
xToX(X1,X2,x1,x2,x1+(i+1)*Real_x_step),
yToY(Y1,Y2,y1,y2,Lagrange(Table,n,x1+(i+1)*Real_x_step)),
3);
}
//在屏幕上顯示一個看起來大一點的點
void PutBigDot(int x,int y,int color)
{
setcolor(color);
circle(x,y,2);
}
//畫函數(shù)表中各點到屏幕上
void DrawPointsInTable(int X1,int Y1,int X2,int Y2,
float x1,float y1,float x2,float y2,
POINT Table[],int n)
{
int i;
for(i=0;i<n;++i)
PutBigDot(xToX(X1,X2,x1,x2,Table[i].x),yToY(Y1,Y2,y1,y2,Table[i].y),14);
}
//畫一點在屏幕上
void DrawPoint_xy(int X1,int Y1,int X2,int Y2,
float x1,float y1,float x2,float y2,
float x,float y)
{
char Digits[60];
int X,Y,tmp;
X=xToX(X1,X2,x1,x2,x);
Y=yToY(Y1,Y2,y1,y2,y);
PutBigDot(X,Y,13);
Digits[0]='(';
gcvt(x,8,&Digits[1]);
tmp=strlen(Digits);
Digits[tmp]=',';
Digits[tmp+1]=0;
gcvt(y,8,&Digits[strlen(Digits)]);
tmp=strlen(Digits);
Digits[tmp]=')';
Digits[tmp+1]=0;
outtextxy(X+3,Y-3,Digits,13);
}
//畫插值曲線和結(jié)果點
void DrawCurve_And_ShowResult(POINT Table[],int n,float x,float y)
{
float Max_x,Max_y;
float x1,y1,x2,y2;
int X1,Y1,X2,Y2;
Table[n].x=x;
Table[n].y=y;
Max_x=GetMaximum_x(Table,n+1);
Max_y=GetMaximum_y(Table,n+1);
x1=-Max_x*2;
y1= Max_y*2;
x2= Max_x*2;
y2=-Max_y*2;
X1=10;
Y1=60;
X2=630;
Y2=450;
DrawCoordinate(X1,Y1,X2,Y2,x1,y1,x2,y2);
DrawFunctionCurve(X1,Y1,X2,Y2,x1,y1,x2,y2,Table,n);
DrawPointsInTable(X1,Y1,X2,Y2,x1,y1,x2,y2,Table,n);
DrawPoint_xy(X1,Y1,X2,Y2,x1,y1,x2,y2,x,y);
}
//函數(shù)表中是不是有x值相同的點,如有相同,則有錯
int Check_x_is_same_as_former(POINT Table[],int i)
{
int k;
for(k=0;k<i;++k)
if(fabs(Table[k].x-Table[i].x)<0.000001) return 1;
return 0;
}
//輸入函數(shù)表
void InputTable(POINT Table[],int *n)
{
int i;
printf("\nNumber of Points n=");
scanf("%d",n);
for(i=0;i<*n;++i)
{
printf("Input %dth point(x%d,y%d): ",i,i,i);
scanf("%f,%f",&Table[i].x,&Table[i].y);
if(Check_x_is_same_as_former(Table,i))
{
printf("\nThis x is the same as the former, ReInput!\n",i);
--i;
}
}
}
//插值函數(shù),這是核心函數(shù),
float Lagrange(POINT Table[],int n,float x)
{
float Result,tmp;
int i,j;
Result=0.0;
for(i=0;i<n;++i)
{
tmp=1.0;
for(j=0;j<n;++j)
{
if(j==i)continue;
tmp*=((x-Table[j].x)/(Table[i].x-Table[j].x));
}
Result+=(tmp*Table[i].y);
}
return(Result);
}
void main()
{
int n;
float x,y;
POINT Table[1000];
//輸入函數(shù)表
InputTable(Table,&n);
//輸入一個x點,即要進行插值計算的點
printf("\nInput x=");
scanf("%f",&x);
//計算Lagrange插值
y = Lagrange(Table,n,x);
//結(jié)果輸出
printf("\nL(%f)=%f",x,y);
printf("\n\nPress any key to show Table,draw L(x) and point (x,y)\n");
getch();
//下面是有關畫曲線和結(jié)果的圖型化顯示
InitGraph();
ShowTable(Table,n);
DrawCurve_And_ShowResult(Table,n,x,y);
outtextxy(1,468,"Press any key to quit!");
getch();
closegraph();
}
//注意
//用TC,BC作圖形化程序時,要在菜單中把link庫中的圖型庫選項打上X,否則有l(wèi)ink時會報錯
/*
運行實例:(注意:當前目錄下必須有egavga.bgi文件)
Number of Points n=3
Input 0th point(x0,y0): 100,10
Input 1th point(x1,y1): 121,11
Input 2th point(x2,y2): 144,12
Input x=115
L(115.000000)=10.722755
Press any key to show Table,draw L(x) and point (x,y)
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -