[erlang-questions] erlang float comparison

Toby Thain <>
Tue May 15 02:34:04 CEST 2012


On 14/05/12 9:53 AM, Angel J. Alvarez Miguel wrote:
> On Lunes, 14 de Mayo de 2012 15:11:52 usted escribió:
>> On 14/05/12 4:47 AM, Angel J. Alvarez Miguel wrote:
>>> Well we just picked the wrong example
>>>
>>>
>>> that's is the problem
>>>
>>> :~>   erl
>>> Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:4:4] [async-threads:0]
>>> [hipe] [kernel-poll:false]
>>>
>>> [QuickCheck] [PropEr] [Erl0MQ]
>>> Eshell V5.9.1  (abort with ^G)
>>> 1>   1.000000000000000002>   1.0.
>>> false
>>
>> It's not clear whether you need an approximate equality test as
>> suggested by others (tolerance won't help you with>  or<  or the example
>> above) or whether you need more (or arbitrary) precision.
>
> Sorry folks, im just a bit puzzled for the strangeness of fp operations
>
> I am talking about things like this:
>
> 8>  1.0000000000000001>  1.0.
> false
> 9>  1.0000000000000002>  1.0.
> true

As others have pointed out, this is not strange at all. These are the 
same values, once precision has been lost by converting the decimal 
string to floating point (which has limited precision, see e.g.[1]).


>
> And i wander that there is some method for avoiding such beasts..
>
> Well ill be happy just if i can compare if Something>  1.0 and it just returns
> false unless Something is really greater than 1.0 (whatever the accuracy is)
> so i can relay on doing things like
>
> if Angle>  1.0 the shutdown_orbital_laser_before_its_too_late().
>


To PROPERLY make these comparisons, you need more precision (e.g. 
BigDecimal, or fixed point/rational which would be simple with Erlang's 
bignum integers).

There are many other issues with floating point, but to deal with the 
above < and > comparisons, you simply need sufficient precision.

--Toby

[1] http://en.wikipedia.org/wiki/IEEE_754-1985


> because we found that:
>   math:acos(0.99999999999999991).
> 1.4901161193847656e-8
>
>   math:acos(0.99999999999999992).
> 1.4901161193847656e-8
>
> math:acos(0.99999999999999993).
> 1.4901161193847656e-8
>
> math:acos(0.99999999999999999).
> 0.0
>
> math:acos(1.0000000000000001).
> 0.0
>
> math:acos(1.0000000000000002).
> ** exception error: bad argument in an arithmetic expression
>       in function  math:acos/1
>          called as math:acos(1.0000000000000002)
>
> this last case is waht we wanted to avoid, specifically
>
> /Angel
>
>>
>> --Toby
>>
>>> On Lunes, 14 de Mayo de 2012 09:50:57 usted escribió:
>>>> 1>   0.99999998<   1.000000.
>>>> true
>>>> 2>   1.99999976<   1.99999988.
>>>> true
>>>>
>>>> What's the problem?
>>>>
>>>> On Mon, May 14, 2012 at 9:41 AM, Angel J. Alvarez Miguel
>>>
>>> <>wrote:
>>>>> **
>>>>>
>>>>>
>>>>> Hi guys
>>>>>
>>>>>
>>>>>
>>>>> I need to compare two floats something like 0.99999998... vs 1.000000
>>>>>
>>>>> and we came across accuracy problems when testing dihedral angles on a
>>>>> molecule...
>>>>>
>>>>>
>>>>>
>>>>> so we read
>>>>> http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.h
>>>>> tm
>>>>>
>>>>> and wanted to implement something like:
>>>>>
>>>>>
>>>>>
>>>>> if (*(int*)&f1<   *(int*)&f2)...
>>>>>
>>>>>
>>>>>
>>>>> when ef1 and f2 are floats... (f1 about 0.9999899.. and f2=1.0
>>>>>
>>>>>
>>>>>
>>>>> is think we should start with...
>>>>>
>>>>>    <<Padding:16,Myint:64>>   =
>>>>>    term_to_binary(1.9999976,[{minor_version,1}]).
>>>>>
>>>>> and let Padding swallow the external format and tag while Myint gets
>>>>> the ieee754 float
>>>>>
>>>>>
>>>>>
>>>>> But MyInt = 4611686017346523993 instead of 1073741822
>>>>>
>>>>> these conversion should follow ieee754 and being lexicografic ordered
>>>>>
>>>>> but ...
>>>>>
>>>>> term_to_binary(1.99999976,[{minor_version,1}]).
>>>>>
>>>>> <<131,70,63,255,255,255,191,147,83,89>>
>>>>>
>>>>> term_to_binary(1.99999988,[{minor_version,1}]).
>>>>>
>>>>> <<131,70,63,255,255,255,223,201,169,173>>
>>>>>
>>>>> doesnt seem to be the same thatn you spect to see after reading that
>>>>> page...
>>>>>
>>>>>    ..What im doing wrong....?
>>>>>
>>>>> ieee754 layout....
>>>>>
>>>>>     +1.99999976
>>>>>
>>>>> 0x3FFFFFFE
>>>>>
>>>>> 1073741822
>>>>>
>>>>> +1.99999988
>>>>>
>>>>> 0x3FFFFFFF
>>>>>
>>>>> 1073741823
>>>>>
>>>>> +2.00000000
>>>>>
>>>>> 0x40000000
>>>>>
>>>>> 1073741824
>>>>>
>>>>> +2.00000024
>>>>>
>>>>> 0x40000001
>>>>>
>>>>> 1073741825
>>>>>
>>>>> +2.00000048
>>>>>
>>>>> 0x40000002
>>>>>
>>>>> 1073741826
>>>>>
>>>>> Thanks!..
>>>>>
>>>>> /Angel
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> erlang-questions mailing list
>>>>> 
>>>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> 
>>> http://erlang.org/mailman/listinfo/erlang-questions
>




More information about the erlang-questions mailing list