Very strange problem with comparing floating point numbers

Maxim Fomin maxim at maxim-fomin.ru
Mon Oct 1 06:07:36 PDT 2012


2012/10/1 monarch_dodra <monarchdodra at gmail.com>:
> On Monday, 1 October 2012 at 11:36:43 UTC, Maxim Fomin wrote:
>>
>> On Sunday, 30 September 2012 at 17:07:19 UTC, monarch_dodra wrote:
>>>
>>> As a rule of thumb, NEVER use opEqual with floating point types aniways.
>>> You need to use some sort of comparison with leway for error, such as
>>> std.math.approxEqual.
>>
>>
>> It is possible to compare exactly floating point types by binary
>> comparison, if it provides some benefits.
>>
>> import std.stdio;
>> import std.math;
>>
>> @property float getFloat()
>> {
>>    return sqrt(1.1);
>> }
>>
>> void main()
>> {
>>    writeln(getFloat is getFloat);  // doesn't fail
>> }
>
>
> I think that what you are comparing here is the functions (the address), and
> not the results of the call. Try
> writeln(getFloat() is getFloat()); //*May* fail
>

http://dpaste.dzfl.pl/1f94c0b1

It works with -m32 too.

 _Dmain:
   0x0806d0e4 <+0>:	push   %ebp
   0x0806d0e5 <+1>:	mov    %esp,%ebp
   0x0806d0e7 <+3>:	sub    $0x10,%esp
   0x0806d0ea <+6>:	push   %esi
   0x0806d0eb <+7>:	push   %edi
   0x0806d0ec <+8>:	call   0x806d0d4 <_D4test8getFloatFNdZf>
   0x0806d0f1 <+13>:	fstps  -0x10(%ebp)
   0x0806d0f4 <+16>:	lea    -0x10(%ebp),%esi
   0x0806d0f7 <+19>:	call   0x806d0d4 <_D4test8getFloatFNdZf>
   0x0806d0fc <+24>:	fstps  -0xc(%ebp)
   0x0806d0ff <+27>:	lea    -0xc(%ebp),%edi
   0x0806d102 <+30>:	mov    $0x4,%ecx
   0x0806d107 <+35>:	xor    %eax,%eax
   0x0806d109 <+37>:	repz cmpsb %es:(%edi),%ds:(%esi)
   0x0806d10b <+39>:	je     0x806d112 <_Dmain+46>
   0x0806d10d <+41>:	sbb    %eax,%eax
   0x0806d10f <+43>:	sbb    $0xffffffff,%eax
   0x0806d112 <+46>:	neg    %eax
   0x0806d114 <+48>:	sbb    %eax,%eax
   0x0806d116 <+50>:	inc    %eax
   0x0806d117 <+51>:	call   0x806d164 <_D3std5stdio14__T7writelnTbZ7writelnFbZv>
   0x0806d11c <+56>:	call   0x806d0d4 <_D4test8getFloatFNdZf>
   0x0806d121 <+61>:	fstps  -0x8(%ebp)
   0x0806d124 <+64>:	lea    -0x8(%ebp),%esi
   0x0806d127 <+67>:	call   0x806d0d4 <_D4test8getFloatFNdZf>
   0x0806d12c <+72>:	fstps  -0x4(%ebp)
   0x0806d12f <+75>:	lea    -0x4(%ebp),%edi
   0x0806d132 <+78>:	mov    $0x4,%ecx
   0x0806d137 <+83>:	xor    %eax,%eax
   0x0806d139 <+85>:	repz cmpsb %es:(%edi),%ds:(%esi)
   0x0806d13b <+87>:	je     0x806d142 <_Dmain+94>
   0x0806d13d <+89>:	sbb    %eax,%eax
   0x0806d13f <+91>:	sbb    $0xffffffff,%eax
   0x0806d142 <+94>:	neg    %eax
   0x0806d144 <+96>:	sbb    %eax,%eax
   0x0806d146 <+98>:	inc    %eax
   0x0806d147 <+99>:	call   0x806d164 <_D3std5stdio14__T7writelnTbZ7writelnFbZv>
   0x0806d14c <+104>:	call   0x806d0d4 <_D4test8getFloatFNdZf>
   0x0806d151 <+109>:	sub    $0x4,%esp
   0x0806d154 <+112>:	fstps  (%esp)
   0x0806d157 <+115>:	call   0x806d588
<_D3std5stdio14__T7writelnTfZ7writelnFfZv>
   0x0806d15c <+120>:	xor    %eax,%eax
   0x0806d15e <+122>:	pop    %edi
   0x0806d15f <+123>:	pop    %esi
   0x0806d160 <+124>:	leave
   0x0806d161 <+125>:	ret

> Also, "is" works like opEqual on built in types, AFAIK, it doesn't use any
> "binary" magic or anything like that.

I don't understand what you are trying to say. Is operator at runtime
compares two objects without calling opEquals functions (if applied on
user-defined types). For built-in and derived types it is similar to
== operator. Although, I am suprised that TDPL and spec doesn't
mention it (focused only on CT usage), there is a paragraph
(http://ddili.org/ders/d.en/null_is.html) from Turkish D book which
clearly shows such usage - so, I think this a valid D feature. Object
comparison at low-level (repz cmpsb) means binary comparison.


More information about the Digitalmars-d-learn mailing list