It may be overkill, but here's a version with everything rounded that gets rid of the extraneous Null
.
Clear[yy];
dx = 1./100; dt = 1./10000;
yy[x0_, t0_] := With[{x = Round[x0, dx], t = Round[t0, dt]},
Which[
x == 0, yy[0, t] = 0,
x == 1, yy[1, t] = 0,
t == 0, yy[x, 0] = Exp[-1000 (x - .3)^2]]
]
Table[With[{
x = Round[x, dx],
t = Round[t, dt],
t2 = Round[t + 3./10000., dt]},
yy[x, t2] = yy[Round[x + 1./100., dx], t] + yy[Round[x - 1./100., dx], t]
],
{t, 0, 3./10000., 3./10000.},
{x, 1./100., 99./100., 1./100.}]
See Memoization of Rounded inputs for related strategies.
Some explanation
The extraneous values of Null
come from Which
, not because Which
is misused by not having a default case, but because of pattern-matching problems in the memoization of yy
. (The OP seems to have noticed something like this in How to stop Mathematica from turning .02 into 0.019999999999999997`, although it is not remarked upon explicitly in the question.)
The underlying cause is round-off error. Note, for instance, that 0.01 + 0.01
equals 0.02`
, while 0.03 - 0.01
equals 0.019999999999999997`
. This is due to numerical round-off error consistent with IEEE 754 binary64 floating-point numbers. Note that 0.02 - (0.03 - 0.01)
equals 2^(-58)
, a one-bit loss of precision.
The problem with the code is subtler, though. While 0.019999999999999997` == 0.02`
returns True
, as patterns, 0.019999999999999997`
does not match 0.02`
. The problem arises specifically in the snippet of the OP's code,
yy[x - 1./100., t]
when x = 0.03
. For t = 3./10000
, the value has been memoized as yy[0.02`, 0.0003`]
; but code snippet evaluates first as yy[0.019999999999999997`, 0.0003`]
, which in turn evaluates to Null
because it does not match yy[0.02`, 0.0003`]
and it falls through the Which
cases. The rounding in the solution I gave, some of which is not strictly necessary, makes the arguments in the memoized definitions and evaluations of yy
match each other when they are meant to be equal.
Round[t, 0.0001]
or something like that? $\endgroup$ – Michael E2 Apr 7 '15 at 0:50x
andt
to multiples of0.01
and0.0001
, which seems appropriate. That would take care of the round-off error. But trying it out, doesn't seem to work. There may be something about your scheme I don't understand yet. $\endgroup$ – Michael E2 Apr 7 '15 at 0:58