`$temp1`

, `$temp2`

, and `$temp3`

, for example, are all MathObject Reals, not Perl reals. That means that when you do comparisons with them, they are fuzzy comparisons. That is, they respect the `tolerance`

and `tolType`

values in the context. Note that this applies not just to equality checks, but also to *inequality*checks as well. This is because you don't want both

`$a == $b`

and `$a > $b`

to be true at the same time. That is, `$a < $b`

, `$a == $b`

, and `$a > $b`

should be mutually exclusive. The MathObject comparisons are arranged to work that way.
In your case, if you get a value like 1822.0004823, this is considered to be equal to 1822 by the fuzzy comparison, so `$tmp3 > $p3`

is false even though `$p3 = 1822`

. Indeed, the limit as *n* goes to infinity of your formula is `$p0*e^(t*r)`

, which is 1822.1188, which is fuzzy-equal to 1822, so you *never* get `$temp3 > $p3`

, and the is why the problem times out.

You probably want to convert to perl reals rather than MathObjects for the computation. You can use `$temp3->value`

for that, as this is the internal Perl real that underlies the MathObject Real. Also, if you are going to be evaluating a MathObject formula multiple times, you may want to create a perl function from the formula rather than calling `eval()`

repeatedly, as that will be much more efficient. For example, `$F = $f->perlFunction`

will get you a perl subroutine reference as `$F`

and you can call `$temp3 = &$F($n3)->value`

to get the Perl real result of the function at `$n3`

.

Even so, however, your loop is pretty inefficient. You could use a faster algorithm, for example the bisection algorithm (or Newton's method if you want to get fancy about it). Here is one approach:

$p0 = 1000; $t = 5; $r0 = 12; $r = $r0/100; $f = Formula("$p0*(1 + $r/n)^($t*n)"); $F = $f->perlFunction; $p1 = 1822; # # Assume the value you want is between these two # (they should be a power of two apart). # $n0 = 12; $n1 = $n0 + 2**10; # # Use bisection to locate the two values that are # one apart on opposite sides of the desired value. # (In this case, it will take 10 iterations to find it # as opposed to the 541 iterations for your version # that simply increments $n3, which is 54 times faster.) # while ($n1 - $n0 > 1) { $n2 = ($n0 + $n1) / 2; $f2 = &$F($n2)->value; if ($f2 > $p1) {$n1 = $n2} else {$n0 = $n2} } # # $n0 is below the value, $n1 is above it. # TEXT($n1);Hope that clears up the issues for you.