MATLAB奇怪错误Gamma函数数值积分

时间:2014-10-23 21:08:11

标签: matlab error-handling gamma-function

我尝试运行以下内容以便以数字方式集成:

nu = 8; 
psi=-0.2;
lambda = 1;
git = @(u) tpdf((0 - lambda * skewtdis_inverse(u, nu, psi)), nu);
g(t,i) = integral(git,1e-10,1-1e-10,'AbsTol',1e-16);

其中tpdf是一个matlab函数,而skewtdis:inverse看起来像这样:

function inv = skewtdis_inverse(u, nu, lambda)
% PURPOSE: returns the inverse cdf at u of Hansen's (1994) 'skewed t' distribution

c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
a = 4*lambda*c*((nu-2)/(nu-1));
b = sqrt(1 + 3*lambda^2 - a^2);

if (u<(1-lambda)/2);
inv = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u/(1-lambda),nu)-a/b;
elseif (u>=(1-lambda)/2);
inv = (1+lambda)/b*sqrt((nu-2)./nu).*tinv(0.5+1/(1+lambda)*(u-(1-lambda)/2),nu)-a/b;
end

我得到的是:

skewtdis_inverse出错(第6行) c = gamma((nu + 1)/ 2)/(sqrt(pi *(nu-2))* gamma(nu / 2));

输出参数&#34; inv&#34; (也许是其他人)在调用&#34; F:\ Xyz \ skewtdis_inverse.m&gt; skewtdis_inverse&#34;。

期间未分配

@(u)tpdf中的错误((0-lambda * skewtdis_inverse(u,nu,psi)),nu)

integralCalc / iterateScalarValued中的错误(第314行)                 fx = FUN(t);

integralCalc / vadapt出错(第133行)             [q,errbnd] = iterateScalarValued(u,tinterval,pathlen);

integralCalc出错(第76行)         [q,errbnd] = vadapt(@ AtoBInvTransform,interval);

积分误差(第89行) Q = integralCalc(fun,a,b,opstruct);

如果我,但是直接调用thr句柄中的函数没有问题:

  
    

tpdf((0 - lambda * skewtdis_inverse(1e-10,nu,psi)),nu)

  

ans =

1.4092e-11

  
    

tpdf((0 - lambda * skewtdis_inverse(1-1e-10,nu,psi)),nu)

  

ans =

7.0108e-10

非常感谢您的努力!

1 个答案:

答案 0 :(得分:0)

默认情况下,integral期望函数句柄采用向量输入。 在您的代码中,if - 语句会创建并发症,因为只有当true的所有元素都满足时,条件才会计算为u 。 因此,如果u是包含大于和小于(1-lambda)/2的元素的向量,则永远不会分配inv

有两种选择:

  1. if - 语句置于for循环中,并迭代u的所有元素。
  2. 使用逻辑索引进行分配。
  3. 对于大量元素计数,第二个选项更快,在我看来,更清晰:

    inv = u; % Allocation
    
    IsBelow =  u <  (1-lambda)/2; % Below the threshold
    IsAbove =  ~IsBelow         ; % Above the threshold
    
    inv(IsBelow) = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u(IsBelow)/(1-lambda),nu)-a/b;
    inv(IsAbove) = (1+lambda)/b*sqrt((nu-2)./nu)*tinv(0.5+1/(1+lambda)*(u(IsAbove)-(1-lambda)/2),nu)-a/b;