I am trying to solve this for sometime, tried searching internet and refering some books, yet have not be able to find a solution.
There is one solution proposed here but not sure if there is any other simpler approach. Refer: Comparing Python dicts with floating point values included
Hope you can give some pointers.
Background: Have dict_A which comes with a {key:{key:{key:[value]}}} relationship. This dict_A will go through an iterative process to optimise its value based on several constraints and an optimization objective. Will stop the optimizing process only when the final optimized dict i.e dict_B2 is equal with the dict optimized one cycle before i.e dict_B1. This gives an impression the dict would not be able to be optimized further and this is used to break the iterative cycle.
Question: As the dicts value contain float number, some stored values get changed, perhaps because dictionary stores value in binary format. Do refer to example below, the variation of the first float value in the dictionary.
dict_B1 = {0: {36: {3: [-1], 12: [0.074506333542951425]}}, 1: {36: {2: [-1], 16: [0.048116666666666676], 17: [-1]}}, 2: {}, 3: {36: {5: [-1], 6: [-1], 15: [0.061150932060349471]}}}
dict_B2 = {0: {36: {3: [-1], 12: [0.074506333542951439]}}, 1: {36: {2: [-1], 16: [0.048116666666666676], 17: [-1]}}, 2: {}, 3: {36: {5: [-1], 6: [-1], 15: [0.061150932060349471]}}}
If I use the below, the interative process goes infinite loop and does not break,
if (dict_B1==dict_B2):
Exit
or,
if (cmp(dict_B1,dict_B2)):
Exit
Is there any other way to compare the dictionaries say, compare with 15 floating point precision from the 18 floating point precision values ?
I tried storing lesser precision values floats in the dictionary. The problem still persist.
Hope you can assist to point me to the right direction.
Update 1: Jakub's Suggestion
Jakub's suggestion is good. I can create two intermediary lists i.e List_B1 and List_B2 to store the floats, these will be used for comparison and as a flag to decide when to break the iterative process.
The below is the code used to test the case. The second item in List_B2 is purposely altered so the value is way above the precision threshold.
def is_equal(floats_a, floats_b, precision=1e-15):
return all((abs(a-b) < precision) for a, b in izip(floats_a, floats_b))
List_B1=[0.074506333542951425,0.048116666666666676,0.061150932060349471]
List_B2=[0.074506333542951439,9.048116666666666676,0.061150932060349471]
print "is_equal(List_B1,List_B2):",is_equal(List_B1,List_B2)
for a, b in izip(List_B1, List_B2):
print a,b, (abs(a-b) < 1e-15)
Results:
is_equal(List_B1,List_B2): True
0.074506333543 0.074506333543 True
0.0481166666667 9.04811666667 False
0.0611509320603 0.0611509320603 True
Strangely is_equal function always returns TRUE which is not correct but when disected the code, it works correctly. Perhaps return all is doing an OR rather than an AND. Still troubleshooting this.
Do share if you have any hints. Will continue to work to solve this. Thanks to Jakub and Julien for all your guidance so far.
rgds Saravanan K
When comparing floating points, always keep in mind that floats are not of infinite precision and accumulate errors. What you are really interested is if two floats are close enough, not if they are equal
If you want to test if two lists of floats are equal, I would do
def is_equal(floats_a, floats_b, precision=1e-15):
return all((abs(a-b) < precision) for a, b in izip(floats_a, floats_b))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With