
On Sat, Dec 6, 2008 at 4:07 PM, Gordon Woodhull <gordon@woodhull.com> wrote:
Robert wrote:
The epsilon solution has already been proposed, but as I understand this (correct me if I'm wrong) it wouldn't work either:
> From: Zach Laine
> Yet another use case would be "close enough is good enough". If the > bounds are within a user-defined epsilon of either boundary.
If I understand correctly, this does not solve the problem either. Let's assume you have two values: x and y, where x = y + eps (eps being the user-defined margin of error). One comparison of x and y would indicate their equality (the difference is not greater than eps), while another one might not if x got truncated in the meantime (and y didn't).
Thanks, I understand the problem now.
I think we are all agreed that the library is orthogonal to any concerns about floating point and nothing needs to be changed in the code. IMO the warning should be toned down in the documentation. I wish the definition that Stjepan suggests were possible, but I don't see how a test can be designed that only only switches from unsatisfied to satisfied.
The epsilon is what makes the difference. Suppose that the invariant condition that we want to enforce is: x < y The problem is that x (and perhaps y, but let's ignore that for simplicity) can at a later point in time go up or down by some dx as a result of truncation. If the condition function tests for x < y, the following things can happen when testing before truncation (I might have mess up some < or <= in there): 1. if x + dx < y, then the condition passes, and it will always pass even after truncation 2. if y <= x - dx, then the condition fails, and it will always fail even after truncation 3. if x < y <= x + dx, then the condition passes, but after truncation it can fail (*this is the problem*) 4, if x - dx < y <= x, then the condition will fail, but after truncation it might pass (this is unfortunate, but does not break the invariant - in any case, it can trigger the policy and the policy can either throw or force truncation and retest or whatever is appropriate). If we keep the invariant at x < y, but the condition actually tests for x + epsilon < y where epsilon >= delta, then you have x + epsilon < y ==> x < y (a passing test guarantees the invariant), as well as x + epsilon < y ==> x + dx < y (a passing condition test guarantees that the validity of the *invariant* won't change). Sure, the passing test does not guarantee that the results of the *test* don't change (the problem pointed out in the quoted text at the beginning), but we don't care about that - we just care that the passed test guarantees that the desired *invariant* does not change. In effect, we are throwing out case 3 above at the expense of expanding the interval in which case 4 (a much more acceptable case) occurs. Another way of describing this would be to say that the library should not necessarily require that the condition test passes if and only if the invariant is satisfied - it should only require that the test fails if the invariant is not satisfied (but if the invariant is satisfied, the test is allowed to fail). Stjepan