[...]
Please give an example of a program which needs such. Then please
explain your test plan.
I've already given several. If you're interested in the least
in cryptology or computer security, you need them.
And while the test plan for my program would be simple (use
something different than /dev/random for the tests), testing
something like /dev/random is pretty awkward. You can do
statistical tests on the output, of course, but in the end, the
correctness of the code is established by code review, more than
by tests.
We seem to be working in different worlds. Mine is the world
of programming software for real-time embedded systems, for
customers like NASA and the military. NASA and the military
are rather picky: They insist that the software we put in
their aircraft, missiles, and spacecraft should not just work
most of the time; they should work _ALL_ the time. Not only
that, they should be proven to work before they are certified.
You cannot present that proof if you can't perform tests that
show that the system doesn't fail for any possible combination
of inputs.
On the embedded systems I've worked on, we simply didn't use
floating point. Beyond that, you can't perform tests for all
possible inputs on anything but the simplest system. For
critical systems, you prove the program is correct (and also use
extensive tests to validate your proofs, of course).
It's easy to say that one has to be careful. That's a given.
But these agency demand a lot more than "careful." They demand
that the stability of the system not depend on careful and
knowledgeable users.
Who's talking about users here? We're talking about programs.
I also develop software for scientific/engineering
applications, especially simulations of real-world systems. As
you have pointed out, real-world systems are by their nature
unpredictable, because they depend on imprecise measurements
and asynchronous events.
But the simulation of those systems must ABSOLUTELY be
predictable, in the sense that equal inputs yield equal
outputs.
We have this rather well-established process called
Validation. It means that every single line of code must do
what is expected of it, over the entire range of its possible
inputs. To validate, we must test the software, using unit
tests, module tests, end-to-end tests, etc., to be certain
that the program performs as its requirement spec said it
should.
You mean that you create a test harness for every single line of
code, independently?
I've worked on critical systems in the past, but we never went
that far. We used a combination of methods, including formal
proofs, code review (and review of the proofs), extensive and
comprehensive testing at all levels (with review to ensure that
the tests were extensive and comprehensive).
You simply cannot satisfy these conditions if the results of
one run don't match those of another, given the same inputs.
In other words, you test for equality, even if the values are
floating point
.
Seriously (and I don't know the answer): how do you validate
software whose requirement is that an external observer cannot
determine a value (a session key, for example) based on data he
can see (the encrypted data passing on the line)? I don't know
how to write a test case for that, and I'm not too sure what I'd
have to look for in a code review.
[...]
Precisely. Which is why one shouldn't depend on that test.
No. Precisely why we should know what we are doing. Just
replacing the test for equality with one for an approximate
equality won't change anything (since the error can be
infinitely big). Rearranging the calculations so that the case
where the results are wrong doesn't occur is the only answer.
And that requires understanding floating point arithmetic, not
applying some simplistic rules.
[...]
Sigh. It should be abundantly obvious that using fp arithmetic
to represent fp arithmetic is exact and predictable. It's a
tautology, so please stop repeating it.
Well, you and others seem to argue against it.
Using fp arithmetic to represent measurements in the real
world is, by necessity, an APPROXIMATION. And while there may
be times -- adding 1.0 and 2.0, for example -- where the
results of the two computations are the same, one cannot count
on this unless one knows in advance that every possible input
will be of the kind that yields exact results.
If your input is an approximation, then the results will be an
approximation. But with what error factor.
I keep coming back to the problem of (a+b)+c != a+(b+c).
Starting with a==1E100, b==-1E100 and c==1.0, it doesn't matter
whether your initial values are exact, or an approximation
+/-10%. The second equation will result in a value that is
completely wrong, period. You have to understand floating point
arithmetic in order to use it safely. And if you understand it,
you know when using equality is appropriate, and when it isn't.
You claim that you do know this, for your application, and I
have no reason to doubt that. But whenever I try to probe a
little deeper, you wander off into discussions of iterations,
and transcendental functions, and similar stuff where you
absolutely cannot know it.
I know what my results represent, and I know how to use them.
At at times, we use exact comparisons. Without any problems.
(In my particular case, after calculating a value, we ensure
that it is the closest possible representation of a multiple of
10^-5.)