May 14, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 5/14/2016 11:46 AM, Walter Bright wrote:
> I used to design and build digital electronics out of TTL chips. Over time, TTL
> chips got faster and faster. The rule was to design the circuit with a minimum
> signal propagation delay, but never a maximum. Therefore, putting in faster
> parts will never break the circuit.
Eh, I got the min and max backwards.
|
May 14, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Saturday, 14 May 2016 at 01:26:18 UTC, Walter Bright wrote:
> On 5/13/2016 5:49 PM, Timon Gehr wrote:
>> And even if higher precision helps, what good is a "precision-boost" that e.g.
>> disappears on 64-bit builds and then creates inconsistent results?
>
> That's why I was thinking of putting in 128 bit floats for the compiler internals.
I almost wonder if the cent/ucent will be avaliable soon as types rather than reserved keywords.
Anyways my two cents. I remember having issues doing a direct compare on an identical value when it was immutable which proved false, and this made no sense and still doesn't. Regardless I've tried to exhaustively do the compares and found some unexpected results.
float f = 1.30;
const float cf = 1.30;
immutable If = 1.30;
writeln(f == 1.30); //false
writeln(cf == 1.30);
writeln(If == 1.30);
writeln(f == 1.30f);
writeln(cf == 1.30f);
writeln(If == 1.30f);
writeln(f == cf);
writeln(f == If); //false
writeln(If == cf);
The real reason it's false is because you're comparing against an immutable (constant), or my results lead me to believe that; Otherwise why could cf and If work?
|
May 14, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | On Saturday, 14 May 2016 at 20:41:12 UTC, Era Scarecrow wrote:
> writeln(f == 1.30f);
> writeln(cf == 1.30f);
> writeln(If == 1.30f);
I guess this returned True ?
|
May 14, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Binarydepth | On Saturday, 14 May 2016 at 20:54:44 UTC, Binarydepth wrote:
> On Saturday, 14 May 2016 at 20:41:12 UTC, Era Scarecrow wrote:
>> writeln(f == 1.30f);
>> writeln(cf == 1.30f);
>> writeln(If == 1.30f);
>
>
> I guess this returned True ?
I only noted the ones that returned false, since those are the interesting cases.
|
May 14, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Monday, 9 May 2016 at 11:26:55 UTC, Walter Bright wrote:
>> I wonder what's the difference between 1.30f and cast(float)1.30.
>
> There isn't one.
I always saw type casting happening @ run-time and "literals" (pardon if that's not the correct term) to happen during compilation. I know that there's no difference in this topic since it is a comparison of values.
|
May 15, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | On Saturday, 14 May 2016 at 20:41:12 UTC, Era Scarecrow wrote:
> The real reason it's false is because you're comparing against an immutable (constant), or my results lead me to believe that; Otherwise why could cf and If work?
The "immutable" is of type real... Unfortunately the "cf" is also computing as real whereas "f" is implicitly converted to real from float. It makes comparing floating point types for equality implementation defined in D, i.e. unreliable.
The assignment to "cf" ought to have brought cf to 32 bit float.
So the "false" results are the correct ones, and the "true" are the unexpected ones where you compare different types.
import numpy
f=numpy.float32(1.30)
r=numpy.float64(1.30)
print r==f # false
|
May 15, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ola Fosheim Grøstad | On Sunday, 15 May 2016 at 06:49:19 UTC, Ola Fosheim Grøstad wrote:
> On Saturday, 14 May 2016 at 20:41:12 UTC, Era Scarecrow wrote:
>> The real reason it's false is because you're comparing against an immutable (constant), or my results lead me to believe that; Otherwise why could cf and If work?
>
> The "immutable" is of type real... Unfortunately the "cf" is also computing as real whereas "f" is implicitly converted to real from float. It makes comparing floating point types for equality implementation defined in D, I.e. unreliable.
But the const and immutable still have to fit within the confines of the size provided, so the fact they were calculated as real doesn't matter when they are stored as floats. If all the results are inverted, I don't see how that works...
Although it does make sense that a float is being promoted up, and the lost precision vs the real is the problem... to which point it should issue a warning for different types.
Does this mean that instead for compares with a float/constant should be demoted down a level if it can? Although I'm sure using the f will force it to be correct.
But then why does f==If fail? It doesn't answer that critical question, since they should be identical.
|
May 15, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | On Sunday, 15 May 2016 at 07:10:49 UTC, Era Scarecrow wrote: > But the const and immutable still have to fit within the confines of the size provided, so the fact they were calculated as real doesn't matter when they are stored as floats. If all the results are inverted, I don't see how that works... The problem is that they aren't stored... It is implementation defined... What is really bad about this is that you have: writeln(f==cf); // true writeln(f==1.30); // false writeln(cf==1.30); // true hence the following fallacy: ((f==cf) && (cf==1.30)) implies (f != 1.30) That is _very_ bad. > Although it does make sense that a float is being promoted up, and the lost precision vs the real is the problem... The problem is that D "optimizes" out casts to floats so that "cast(real)cast(float)somereal" is replaced with "somereal": writeln(1.30==cast(real)cast(float)1.30); // true > But then why does f==If fail? It doesn't answer that critical question, since they should be identical. Because D does not cancel out "cast(real)cast(float)1.30)" for "f", but does cancel it out for cf. Or basically: it uses textual substitution (macro expansion/inlining) for "cf", but not for "f". ? |
May 15, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Stouffer | On Friday, 13 May 2016 at 03:18:05 UTC, Jack Stouffer wrote:
> On Friday, 13 May 2016 at 01:03:57 UTC, Walter Bright wrote:
>> I've actually been thinking of writing a 128 bit float emulator, and then using that in the compiler internals to do all FP computation with.
>>
>> It's not a panacea, as it won't change how things work in the back ends, nor will it change what happens at runtime, but it means the front end will give portable, consistent results.
>
> And be 20x slower than hardware floats. Is it really worth it?
Yes. What is the proportion of CTFE floating point operation right know in the total compile time ? I'd be highly supersized if it was anything close to 1% .
|
May 15, 2016 Re: Always false float comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On Sunday, 15 May 2016 at 12:11:58 UTC, deadalnix wrote:
> Yes. What is the proportion of CTFE floating point operation right know in the total compile time ? I'd be highly supersized if it was anything close to 1% .
That was said about CTFE in general before people started to use it and discovered it is unusable because of performance issues (vibe.d is a prominent example).
|
Copyright © 1999-2021 by the D Language Foundation