It seems that R qt can use a completely different algorithm than Matlab tinv . I think you and others should report this flaw to The MathWorks by submitting a service request . By the way, in R2014b and R2015a, instead of NaN , -Inf returned for small values (about eps/8 or less) of the first argument p . This is more reasonable, but I think they should do better.
At the same time, there are several workarounds.
Special occasions
Firstly, in the case of t-distribution for students there are several simple analytical solutions for the inverse function of the CDF or for certain integer parameters ν. For your example, ν = 2:
% for v = 2 p = 1e-18; x = (2*p-1)./sqrt(2*p.*(1-p))
which returns -7.071067811865475e+08 . At a minimum, Matlab tinv should include these special cases (they only do this for ν = 1). This is likely to improve the accuracy and speed of these specific solutions.
Numerical inverse
The tinv function tinv based on the betaincinv function. It seems that it is this function that is responsible for the loss of accuracy for small values of the first argument, p . However, as the OP suggested, you can use the CDF function, tcdf and root search methods to quantify the reverse CDF. The tcdf function tcdf based on betainc , which does not look as sensitive. Using fzero :
p = 1e-18; v = 2 x = fzero(@(x)tcdf(x,v)-p, 0)
This returns -7.071067811865468e+08 . Note that this method is not very stable for p values close to 1 .
Symbolic decisions
For more general cases, you can use symbolic math and variable precision arithmetic . You can use identities in terms of Gaussian hypergeometric functions , 2 F 1 , as here for CDF. Thus, using solve and hypergeom :
% Supposedly valid for or x^2 < v, but appears to work for your example p = sym('1e-18'); v = sym(2); syms x F = 0.5+x*gamma((v+1)/2)*hypergeom([0.5 (v+1)/2],1.5,-x^2/v)/(sqrt(sym('pi')*v)*gamma(v/2)); sol_x = solve(p==F,x); vpa(sol_x)
The tinv function tinv based on betaincinv . The Symbolic Math or MuPAD toolbar does not have an equivalent function or even an incomplete beta function, but a similar 2 F 1 ratio for an incomplete beta function :
p = sym('1e-18'); v = sym(2); syms x a = v/2; F = 1-x^a*hypergeom([a 0.5],a+1,x)/(a*beta(a,0.5)); sol_x = solve(2*abs(p-0.5)==F,x); sol_x = sign(p-0.5).*sqrt(v.*(1-sol_x)./sol_x); vpa(sol_x)
Both symbolic circuits return results that agree with -707106781.186547523340184 , using the default digits .
I have not fully confirmed the two character methods above, so I cannot vouch for their correctness in all cases. The code also needs to be vectorized and will be slower than a fully numerical solution.