Erlang Central

Floating Point Compare

Revision as of 15:22, 24 September 2006 by Ayrnieu (Talk | contribs)

Problem

You want to compare two floating-point numbers and know if they are equal. Unfortunately, floating-point arithmetic is not precise so very few results will match exactly. Consequently, we usually want to compare floating point values up to a certain number of decimal places.

Solution

Implement a "fuzzy match" on two real numbers where the difference is below some epsilon threshhold.

In these cases, you can use floating-point byte strings to represent and compare numbers:

1> Aval = 8.001e-3 * 9.001e5.
7201.70
2> Bval = 8.0011e-3 * 9.001e5.
7201.79
3> Aval == Bval.
false
4> ABin = << Aval/float >>.
<<64,188,33,179,57,192,235,237>>
5> BBin = << Bval/float >>.
<<64,188,33,202,68,166,34,63>>
6> << ABinTest:3/binary, ARest:5/binary >> = ABin.
<<64,188,33,179,57,192,235,237>>
7> ABinTest.
<<64,188,33>>
8> << BBinTest:3/binary, BRest:5/binary >> = BBin.
<<64,188,33,202,68,166,34,63>>
9> BBinTest.
<<64,188,33>>
10> BinTest == BinTest2.
true
11> << ABinTest2:4/binary, ARest2:4/binary >> = ABin.
<<64,188,33,179,57,192,235,237>>
12> << BBinTest2:4/binary, BRest2:4/binary >> = BBin. 
<<64,188,33,202,68,166,34,63>>
13> ABinTest2 == BBinTest2.
false

Another option is to convert the numbers into strings and then compare the portions of the numbers of interest:

14> [Nsa]=io_lib:format("~.12f", [Aval]).
["7201.700099999999"]
15> [NSB]=io_lib:format("~.12f", [Bval]).  
["7201.790110000001"]
16> string:substr(NSAa, 1, 6) == string:substr(NSB, 1, 6).
true

A final thought:

20> Equal_to_digit = fun(Digit, Numa, Numb) ->                     
20> [N_a] = io_lib:format("~.12f", [Numa]),                   
20> [N_b] = io_lib:format("~.12f", [Numb]),   
20> string:substr(N_a, 1, Digit) == string:substr(N_b,1,Digit) end.
#Fun<erl_eval.18.83214871>
21> Equal_to_digit(6, Aval, Bval).
true

Note: Some error handling would obviously be necessary to handle cases where the digits are insufficient for the match.

See Also

Volume 2, Section 4.2.2 of The Art of Computer Programming