[置顶] Chebyshev 展开

Chebyshev展开是将有限区间上的光滑函数以Chebyshev多项式为基做展开。和Taylor展开不同的是,它对展开函数的光滑性要求较低,只需连续即可。著名的Chebfun系统基础之一就是Chebyshev展开。下面是Mathematica上的一个简单的Chebyshev展开,展开系数使用Gauss-Chebyshev积分计算,积分的代数精度是2*M+1,这里M是展开的阶数。

(************************************************************************)
(*                         Chebyshev approximation                      *)
(************************************************************************)
ChebyshevApproximation[f_, x_, a_, b_, M_] := Module[{tmp, i, j, z, F, A},
	(*M:{1,x,x^2,...,x^M}*)
	(* Comment: A[j] is accurate for polynomials of degree less than 2M+1 *)
	If[FreeQ[f,x],Return[f]];
	tmp[0] = f /. x -> a + (b - a)*(z + 1)/2;
	If[Length[nodes] != M + 1, 
		(* global nodes and T to avoid reduplicate computation*)
		nodes = Table[Cos[(2*i + 1)*Pi/(2*(M + 1))] // GetDigit, {i, 0, M}];
		T = Table[ChebyshevT[i, nodes[[j]]], {i, 0, M}, {j, 1, M + 1}]
	];
	F = tmp[0] /. z -> nodes // Expand;
	For[j = 0, j <= M, j++,
		A[j] = 2/(M + 1)*F.T[[j + 1]] // GetDigit;
	];
	tmp[1] = A[0]/2 + Sum[A[j]*ChebyshevT[j, z], {j, 1, M}];
	tmp[2] = tmp[1] /. z -> -1 + 2*(x - a)/(b - a) (*// Expand//GetDigit*)
];

这里GetDigit是自定义的一个函数,其作用是保持数字的有效位,默认是100位。

(************************************************************************)
(*                             Define  GetDigit[]                       *)
(************************************************************************)
(* 2012.01.05, 12:21, happy!! *)
Naccu=100;
GetDigit[p_Plus] := Map[GetDigit, p];
GetDigit[p_List] := Map[GetDigit, p];
GetDigit[p_Complex]:=GetDigit[Re[p]]+I*GetDigit[Im[p]];
GetDigit[c_Real]    := 0 /;Abs[c] < 10^(-Naccu+1);
GetDigit[c_*f_] := GetDigit[c]*f /; NumericQ[c];
GetDigit[f_] := f /; !NumericQ[f];
GetDigit[c_] := SetPrecision[Apply[Rationalize[#1]*10^#2&,MantissaExponent[c]],Naccu]/;NumericQ[c]


Maple中的Chebyshev 级数展开,展开长度M由eps自适应决定,帮助文件说“The series computed is the ‘infinite’ Chebyshev series, truncated by dropping all terms with coefficients smaller than eps muliplied the largest coefficient”,函数chebyshev的源代码如下:

> with(numapprox);

>interface(verboseproc = 2);

>print(chebyshev);

proc(f::{algebraic,procedure},eqn::{name,name=algebraic..algebraic,algebraic..algebraic},eps::numeric,size::integer)
	option `Copyright (c) 1992 by the University of Waterloo. All rights reserved.`; 
	local f_is_operator,x,r,epsilon,oldDigits,a,b,evalhfOK,fproc,err,nofun,c,intf,tol,maxcoef,k,K,s,y,flags,dim,g; 
	if nargs<2 or 40 or max(epsilon*abs(intf),0.001*epsilon)+Float(1,-Digits)evalf(v/d),[seq(c[k],k=1..nofun)],nofun - 1); 
	maxcoef:=max(1,op(c)); 
	tol:=1/5*epsilon*maxcoef; 
	for K from nofun by -1 to 1 while abs(c[K])0. or b - 1.0<>0. then 
			userinfo(2,'`numapprox:-chebyshev`',nprintf("even coefficents are zero -- transform to interval -1..1")); 
			a:=op(1,r); 
			b:=op(2,r); 
			g:=eval(f,x=1/2*(b - a)*y+1/2*a+1/2*b); 
			s:=procname(g,y=-1..1,epsilon,dim); 
			s:=subs(y=2*x/(b - a) - (a+b)/(b - a),s) 
		else 
			userinfo(2,'`numapprox:-chebyshev`',nprintf("function is odd -- try f(x)/x")); 
			Digits:=Digits+2; 
			s:=procname(f/x,x=r,1/100*epsilon); 
			s:=numapprox:-chebmult('T'(1,x),s); 
			Digits:=Digits - 2; 
			if type(s,`+`) then s:=map(proc(t,tol) if abs(lcoeff(t))




转载于:https://www.cnblogs.com/seventhsaint/archive/2013/01/13/2872069.html

你可能感兴趣的:([置顶] Chebyshev 展开)