3
$\begingroup$
In[3]:= n = 5; n1 = 4; n2 = 6; γ = 0.05; α = 1/370;
InverseCDF[NoncentralFRatioDistribution[1, n1 - 1, n1/γ^2], 
 1 - α - (n - n1)/n2]

During evaluation of In[3]:= FindRoot::lstol: The line search decreased the step size to within tolerance specified by AccuracyGoal and PrecisionGoal but was unable to find a sufficient decrease in the merit function. You may need more than MachinePrecision digits of working precision to meet these tolerances. >>

Out[4]= 3.24659

The correct answer is 5468.146427955789

$\endgroup$

1 Answer 1

6
$\begingroup$

Use FindRoot directly with arbitrary-precision

n = 5; n1 = 4; n2 = 6; γ = 1/20; α = 1/370;

icdf = x /. 
  FindRoot[CDF[NoncentralFRatioDistribution[1, n1 - 1, n1/γ^2], x] == 
    1 - α - (n - n1)/n2, {x, 500}, 
   WorkingPrecision -> $MachinePrecision]

(* 5468.146403807255 *)

Verifying,

(CDF[NoncentralFRatioDistribution[1, n1 - 1, n1/γ^2], icdf] // 
   RootApproximant) === 1 - α - (n - n1)/n2

(* True *)

Note that while the starting value used in FindRoot needs to be large, it does not have to be particularly close to the actual value.

EDIT: To "correct" the InverseCDF define your own function

Clear["Global`*"]

n = 5; n1 = 4; n2 = 6; γ = 1/20; α = 1/370;

invCDF[dist_, q_, start_: 50, wkprec_: $MachinePrecision] :=
 Module[
  {x, distr = Rationalize[dist], qr = Rationalize[q]},
  Check[InverseCDF[dist, q],
   x /. FindRoot[CDF[distr, x] == qr, {x, start},
     WorkingPrecision -> wkprec]]]

dist = NoncentralFRatioDistribution[1, n1 - 1, n1/γ^2];

Exact input to invCDF will output exact output (i.e., unevaluated for your example distribution). Since InverseCDF does not throw an error message, switching to FindRoot does not occur.

invCDF[dist, 1 - α - (n - n1)/n2]

(* InverseCDF[NoncentralFRatioDistribution[1, 3, 1600], 461/555] *)

This is desired for less complicated distributions for which the InverseCDF is known, e.g.,

invCDF[NormalDistribution[], 3/4]

(* Sqrt[2] InverseErfc[1/2] *)

Converting the argument for your distribution to a numeric approximation will result in evaluation and the desired switching to FindRoot.

invCDF[dist, 1 - α - (n - n1)/n2 // N] // Quiet

(* 5468.146403807255 *)
$\endgroup$
3
  • $\begingroup$ See edit for "corrected" function. $\endgroup$
    – Bob Hanlon
    Jan 16, 2019 at 15:52
  • $\begingroup$ Thanks a lot for your effort. The problem is you have fixed the starting value at 50 in the findroot function, which will not be the good choice in general. The starting value maybe 0.5. It means, every time we need to put the correct starting value. The built-in inverseCDF function, however, doesn't require any starting value. The problem is thus still there!! $\endgroup$
    – Abdul Haq
    Jan 17, 2019 at 20:19
  • $\begingroup$ The starting value is not fixed at 50 it defaults to 50. You can specify any starting value that you want. The default used by InverseCDF isn't working so I gave you the ability to specify one. $\endgroup$
    – Bob Hanlon
    Jan 17, 2019 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.