Floating Point Compare
From ErlangCentral Wiki
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.
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:
-module(fp). -export([fuzzy_match/3]). fuzzy_match(A,B,L) -> <<AT:L/binary, _/binary>> = <<A/float>>, <<BT:L/binary, _/binary>> = <<B/float>>, AT == BT.
1> A = 8.001e-3 * 9.001e5. 7201.70 2> B = 8.0011e-3 * 9.001e5. 7201.79 3> A == B. false 4> fp:fuzzy_match(A,B,3). true 5> fp:fuzzy_match(A,B,4). false
Another option is to convert the numbers into strings and then compare the portions of the numbers of interest:
-module(fps). -export([equal_to_digit/3]). equal_to_digit(A,B,D) -> [As0,Bs0] = io_lib:fwrite("~.*f~.*f", [D+1,A-trunc(A),D+1,B-trunc(B)]), As = string:substr(As0,1,D+2), Bs = string:substr(Bs0,1,D+2), As == Bs.
5> fps:equal_to_digit(7201.700099999999, 7201.790110000001,1). true 6> fps:equal_to_digit(7201,700099999999, 7201.790110000001,2). false
Note: Some error handling would obviously be necessary to handle cases where the digits are insufficient for the match.
Volume 2, Section 4.2.2 of The Art of Computer Programming