approxEqual() has fooled me for a long time...

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Wed Oct 20 08:25:38 PDT 2010


On 10/20/10 5:57 CDT, Don wrote:
> Lars T. Kyllingstad wrote:
>> (This message was originally meant for the Phobos mailing list, but
>> for some reason I am currently unable to send messages to it*. Anyway,
>> it's probably worth making others aware of this as well.)
>>
>> In my code, and in unittests in particular, I use std.math.approxEqual()
>> a lot to check the results of various computations. If I expect my
>> result to be correct to within ten significant digits, say, I'd write
>>
>> assert (approxEqual(result, expected, 1e-10));
>>
>> Since results often span several orders of magnitude, I usually don't
>> care about the absolute error, so I just leave it unspecified. So far,
>> so good, right?
>>
>> NO!
>>
>> I just discovered today that the default value for approxEqual's default
>> absolute tolerance is 1e-5, and not zero as one would expect. This
>> means that the following, quite unexpectedly, succeeds:
>>
>> assert (approxEqual(1e-10, 1e-20, 0.1));
>>
>> This seems completely illogical to me, and I think it should be fixed
>> ASAP. Any objections?
>
> I'm personally pretty upset about the existence of that function at all.
> My very first contribution to D was a function for floating point
> approximate equality, which I called approxEqual.
> It gives equality in terms of number of bits. It gives correct results
> in all the tricky special cases. Unlike a naive relative equality test
> involving divisions, it doesn't fail for values near zero. (I _think_
> that's the reason why people think you need an absolute equality test as
> well).
> And it's fast. No divisions, no poorly predictable branches.
>
> Unfortunately, somebody on the ng insisted that it should be called
> feqrel(). Stupidly, I listened. And now nobody uses my masterpiece
> because it has a totally sucky name.

Hi Don,

Any chance you could please integrate feqrel within approxEqual? It's 
not exactly the code I'd be most proud of.

As a side note, I keep on thinking of syntactic cutesies related to 
approxEqual. I think doubles should be compared for equality very 
rarely, so approximate comparisons should be easy to read and write. For 
example:

double a, b;
...
if (a == within(1e-5) == b) { ... }

The condition is true when a is within 1e-5 from b. One issue is that 
"within" conveys absolute distance, when most of the time you want 
relative. Using e.g. withinPercent is clearer but not cute anymore.

Any ideas? The feqrel and approxEqual story does seem to suggest that 
names (and by extension syntax) are important.


Andrei


More information about the Digitalmars-d mailing list