PDA

View Full Version : Compare two doubles



duluter
02-02-2010, 09:01 AM
Hi, all.

I was reading that a "safe" way to test equality of two double-type variables is to compute the absolute value of their difference and then compare that to some predetermined acceptable error margin. So, if the absolute difference is less than 0.0000001, then they are considered equal (for example).

I was wondering if there is a reason why you couldn't just round the two variables, say to 6 decimals (or whatever number of decimals suits your needs), and then compare them directly:

Double var1 = 10.900000001
Double var2 = 10.900000000

If Round(var1, 6) = Round(var2, 6) Then 'They're equal.

Would this work?


Thanks,

Duluter

RolfJ
02-02-2010, 10:24 AM
YES.

PS: A little experimenting goes a long way

duluter
02-02-2010, 10:33 AM
Thank you for the reply.

I did try it, and it did work, but I thought that experimenting with some random numbers is a poor way to validate if it works or not--it was conceivable to me that it could work for some values and not for others because my knowledge of how these things work "behind the scenes" is not too good. It seemed to me that round-and-compare was easier than take-absolute-values-and-compare-to-predetermined-error-margin and since the recommendations I saw were for the latter, I thought I might be missing something.

ZVI
02-02-2010, 04:50 PM
NO! ;)

What if the compared are 1000000000000.01 and 1000000000000.02, but you trust to only 12 significant digits?

I would suggest using such function:


Function IsEqual(v1#, v2#, Optional Digits% = 12) As Boolean
Dim v, i%
v = Fix(v1)
i = Digits - Len(v) + IIf(v = 0, 1, 0)
If i < 0 Then
IsEqual = Round(v1 / 10 ^ -i, 0) = Round(v2 / 10 ^ -i, 0)
Else
IsEqual = Round(v1, i) = Round(v2, i)
End If
End Function

Regards,
Vladimir

ZVI
02-02-2010, 05:46 PM
And this one is for comparing of the doubles in its full range with required significant digits.


Function IsEqual(v1#, v2#, Optional SignificantDigits% = 12) As Boolean
Dim f$
If v1 = v2 Then
IsEqual = True
Else
f = String(SignificantDigits, "0") & "E+0"
IsEqual = Format(v1, f) = Format(v2, f)
End If
End Function

Sub Test()
Dim v1#, v2#
v1 = 1.23456789012345E+100
v2 = 1.23456789012346E+100
Debug.Print IsEqual(v1, v2) ' <- SignificantDigits = 12 as default
Debug.Print IsEqual(v1, v2, 14) ' = True
Debug.Print IsEqual(v1, v2, 15) ' = False
End Sub

Aussiebear
02-02-2010, 06:06 PM
Good point ZVI, however the depth of accuracy may well depend on the acceptable standards within any particular industry.