One useful feature of the `evalf` command is that it remembers previous results. But it also stores the current value of Digits as well as its input argument, to be associated with the remembered result.

There are two reasons for this. The fancier reason is so that, when Digits is reduced from that of an earlier successful computation, `evalf` can simply round off the earlier result to the desired number of decimal digits. The more basic reason is that `evalf` might well need to redo the computation at the higher working precision, in the case that Digits has increased since the previous successful computation.

The question then comes up: what other commands which rely upon floating-point calculations will themselves remember inputs & results (in their own remember tables or Caches, or in tables/Caches of some internal routine underneath their top-level entry point)? If such commands don't associate both input and Digits alongside remembered results, then won't they sometimes fail to work properly? The answer is yes.

And I know of two such commands: `is` and `identify`. (The `identify` command is currently implemented as an appliable module, and identify:-ModuleApply has `option remember,system`.)

Here's an identify example, that came up in another forum:

> restart:

> s:=1.218041583332573;
1.218041583332573

> identify(s); # call A
1.218041583332573

> Digits:=15:

> identify(s); # call B
1.218041583332573

> forget(identify);

> identify(s); # call C
1 (1/2) 3
-- 2 Pi
36

What happends is that the input & result from call A gets remembered. Then call B returns the same remembered result immediately, and it doesn't recompute even though Digits has been raised. (Another hint that this occurs is the fact that it returns from call B immediately, with no elasped time taken.)

But if one forcibly clears whatever remember table/Cache is stored, then call C will recompute the result. And call C is done with the higher working precision. High enough to allow it to succeed.

One could argue that, since floating-point calculations are likely of central importance to `identify`, it too should remember both Digits and the input.

This problem can come up for other so-called environment variables, of which Digits is just one example. But it is the one which arises most often, I suspect.

Now, one might also wonder why Digits had to be 15 for identify to succeed. That seems to be the lowest value of Digits for which this example succeeds with default options to `identify`.

> restart:

> s:=1.218041583332573;
1.218041583332573

> for d from 10 to 60 do
> Digits:=d:
> forget(identify);
> x := identify(s);
> if not(type(x,float)) then
> print(d,x);
> break;
> end if;
> end do:

1 (1/2) 3
15, -- 2 Pi
36

But is it just because of length of `s` is not a match to the working precision? It seems that the answer is not that simple. The following revision to the search, which first rounds `s` to the current working precision, shows that it's not just a length vs Digits mismatch that prevents `identify` from finding a result at a lower working precision.

> restart:

> s:=1.218041583332573;
1.218041583332573

> for d from 10 to 60 do
> Digits:=d:
> forget(identify);
> sbar:=evalf(s);
> x := identify(sbar);
> if not(type(x,float)) then
> print(d,x);
> break;
> end if;
> end do:

1 (1/2) 3
15, -- 2 Pi
36

So it looks more as if success for this example depends on something more interesting happening inside the computation. I haven't looked yet, to see just what. But it looks like at least 14 decimal places of s are needed, and at least Digits=15, for `identify` to succeed with its default options on this example.

acer


Please Wait...