Always false float comparisons
Ola Fosheim Grøstad via Digitalmars-d
digitalmars-d at puremagic.com
Tue May 17 22:49:16 PDT 2016
On Wednesday, 18 May 2016 at 03:01:14 UTC, Joakim wrote:
> There is nothing "random" about increasing precision till the
> end, it follows a well-defined rule.
Can you please quote that well-defined rule?
It is indeed random, or arbitrary (which is the same thing):
if(x<0){
// DMD choose 64 bit mantissa
const float y = ...
...
} else {
// DMD choose 24 bit mantissa
float y = ...
...
}
How is this not arbitrary?
If x is the amplitude then a flaw like this can cause a DC offset
to accumulate and you end up with reduced precision, not improved
precision. A DC filter at the end does not help on this precision
loss.
> So you're planning on running phase-locking code partially in
> CTFE and runtime and it's somehow very sensitive to precision?
> If your "phase-locking" depends on producing bit-exact results
> with floating-point, you're doing it wrong.
I am not doing anything wrong. D is doing it wrong. If you add
different deltas then you will get drift. So, no improved
precision in calculating some deltas is not improving the
accuracy. It makes it worse.
> If any of this depends on comparing bit-exact floating-point
> results, you're doing it wrong.
It depends on the unit tests running with the exact same
precision as the production code.
Fast floating point code depends on the specifics of the
hardware. A system level language should not introduce a
different kind of bias that isn't present in the hardware!
D is doing it wrong because it makes it is thereby forcing
programmers to use algorithms that are 10-100x slower to get
reliable results.
That is _wrong_.
> If the constant is calculated rather than a literal, you should
> be checking using approxEqual.
No. 1+2+3+4 is exact on all floating point units I know of.
>> 3. Comparing for equality is the same as subtraction followed
>> by testing for zero.
>
> So what? You should be using approxEqual.
No.
>> So, the rule is: you shouldn't compare at all unless you know
>> the error bounds, but that depends on WHY you are comparing.
>
> No, you should always use error bounds. Sometimes you can get
> away with checking bit-exact equality, say for constants that
> you defined yourself with no calculation, but it's never a good
> practice.
It is if you know WHY you are doing a test.
Btw, have you ever tried to prove error bounds for an iterative
method?
You actually think most people prove them to be correct?
Or perhaps almost all of them just pick a number out of thin air
which they think will work out and rely on testing their code?
Well, the latter is no better than checking for exact equality.
And I can assure you that the vast majority of programmers do not
prove error bounds with the level of rigour it takes to get it
correct.
The reality is that it is common practice to write code that
seems to work. But that does not make it correct. However, making
it correct is way too time consuming and often not worth the
trouble. So people rely on testing. Floating point code is no
different.
But with D semantics you cannot rely on testing. That's bad,
because most people write incorrect code. Whether they are
experts or not. (it is only matter of difference in frequency)
>> f(x) = 1/(2-x)
>>
>> Should I not be able to test for the exact value "2" here?
>
> It would make more sense to figure out what the max value of
> f(x) is you're trying to avoid, say 1e6, and then check for
> approxEqual(x, 2, 2e-6). That would make much more sense than
> only avoiding 2, when an x that is arbitrarily close to 2 can
> also blow up f(x).
I am trying to avoid an exception, not a value.
> Oh, it's real world alright, you should be avoiding more than
> just 2 in your example above.
Which number would that be?
> Simply repeating the word "random" over and over again does not
> make it so.
That's right. It is DMD that makes it so, not my words.
However, in order to reject what other say, you have to make an
argument. And in this case we have:
1. A system level programming language that claims to excel at
floating point.
2. Hardware platforms with specific behaviour.
Unfortunately 2 is true, but not 1.
D is not matching up to the minimum requirements for people
wanting to write fast and reliable floating point code for a
given platform.
According to the D spec, the compiler could schedule typed single
precision floating point calculations to two completely different
floating point units (and yes, there are platforms that provide
multiple incompatible floating point units with widely differing
characteristics).
That is random.
And so is "float" behaving differently than "const float".
More information about the Digitalmars-d
mailing list