2
$\begingroup$

In my code I have function which takes large value, e.g. y[x_]=10^15 (2 - x^2) When I try to find a root for such function, FindRoot reports it does not succeded:

x1 = x /. FindRoot[ y[x] == 0, {x, 1, 2}];
x1 // FullForm

FindRoot::cvmit: Failed to converge to the requested accuracy or precision within 100 iterations.

1.4142135623730951`

in fact, it's correct answer

Sqrt[2.] // FullForm

1.4142135623730951`

I understand that FindRoot checks the absolute error of function value in subsequent steps, $(y_{i+1}-y_i)< \epsilon $. Is there any way to force FindRoot to test relative error, that means $\frac{(y_{i+1}-y_i)}{y_i} < \epsilon$ ?

$\endgroup$
  • $\begingroup$ Is it clear that ${(y_{i+1}-y_i)}/{y_i}$ converges to zero? In a well-behaved Newton's method problem at a simple root, I think it should converge to 1. $\endgroup$ – Michael E2 Apr 21 at 20:34
  • $\begingroup$ you're right, if the root is simple ($y'(x_{root})\neq 0$) the ratio goes to 1. But what happens for double root, $y'(x_{root}) = 0$ ? $\endgroup$ – sebqas Apr 26 at 9:32
  • $\begingroup$ If the root is of multiplicity $n$, then the ratio converges to $1-\left(\frac{n-1}{n}\right)^n$. $\endgroup$ – Michael E2 Apr 26 at 13:51
3
$\begingroup$
y[x_] = 10^15 (2 - x^2);

Specify a WorkingPrecision for FindRoot. This results in the use of arbitrary-precision rather than machine precision.

x1 = (x /. FindRoot[y[x] == 0, {x, 1, 2}, WorkingPrecision -> #]) & /@ {20, 
   25, 30}

(* {1.4142135623730950488, 
    1.414213562373095048801689, 
    1.41421356237309504880168872421} *)

y /@ x1

(* {0.*10^-5, 0.*10^-10, 0.*10^-15} *)

Note that there is a significant loss of precision (15 digits).

EDIT: In this case Simplify resolves the problem since it will remove the constant factor.

x1 = x /. FindRoot[y[x] == 0 // Simplify, {x, 1, 2}]

(* 1.41421 *)
| improve this answer | |
$\endgroup$
  • $\begingroup$ you're right, it's a typo, it should be 10^15(2-x^2), I've corrected . $\endgroup$ – sebqas Apr 23 at 20:58
0
$\begingroup$

I don't think there's an easy way, because the stopping criterion is probably not robust. But here's a way to use the StepMonitor to stop when the adjusted relative criterion $\left|\,\left| {y_{i+1}-y_i \over y_i}\right| -1 \right|< \epsilon$, which will lead to a finite number of steps if Newton's method has quadratic convergence on the given problem like in OP's example:

y[x_] = 10^15 (2 - x^2);

Module[{x1 = 1, x2 = 2, y1, y2, eps = 10^-4},
 y1 = y[x1]; y2 = y[x2];
 FindRoot[y[x] == 0, {x, 1, 2},
  StepMonitor :> (
    y2 = y1; y1 = y[x];
    If[y1 == 0 || (x1 != x && Abs[Abs[(y1 - y2)/y2] - 1] < eps),
     Return[{HoldPattern[x] -> x}, Module],
     x1 = x])
  ]
 ]
(*  {HoldPattern[x] -> 1.41421}  *)

y[x] /. First@%
(*  -117.24  *)

In some problems, one might need to raise AccuracyGoal and PrecisionGoal if you do not want them to stop FindRoot. To effectively turn off PrecisionGoal, raise it above the WorkingPrecision. To turn off AccuracyGoal, set it to Infinity. FindRoot will not allow both to be set to Infinity.

| improve this answer | |
$\endgroup$
  • $\begingroup$ thanks for the ready-to-work routine. I thought I can avoid using StepMonitor. Also, the remark on the AccuracyGoal and PrecisionGoal is helpfull. $\endgroup$ – sebqas Apr 26 at 9:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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