1

Everyone.

I've come into a strange problem where when I try to compare two identical lists, Python (2.7) determines that they are disparate. They are embedded in a rather large body of code, but here is small piece of it.

print("innersearch:",innersearch)
print("innersub:",innersub)
if (innersearch == innersub):
     print("innersearch = innersub")
print("----")

Unfortunately, this returns:

innersearch: (-100.00,-0.00)
innersub: (-100.00,-0.00)
----

I know this is a modal issue, because when I replace innersearch and innersub with (-100.00,-0.00) for both, I get innersearch = innersub. Any help is appreciated, and apologies for my lack of knowledge.

UPDATE:

It was suggested that I round the values, as they had been when outputted before comparing them, and, unfortunately, this did little to help.

innersub = turtle.Vec2D(round(innersub[0], 2), round(innersub[1], 2))
innersearch = turtle.Vec2D(round(innersearch[0], 2), round(innersearch[1], 2))
print("innersearch:",innersearch)
print("innersub:",innersub)
if (innersearch == innersub):
    print("innersearch = innersub")
print("----")

And this returned the same. Any ideas?

5813
  • 1,073
  • 3
  • 14
  • 28
  • Are they lists or tuples? – Xymostech Nov 29 '13 at 17:56
  • 8
    My guess is that there's a very slight difference in the floating point values, such that they both round to the same number when displayed, but they're not actually equal. – DaoWen Nov 29 '13 at 17:57
  • 1
    Add a couple lines of debug code to test @daowen's hypothesis: `for i in xrange(len(list1)): print list1[i] - list2[i]`. – Chris Johnson Nov 29 '13 at 18:02
  • Rule of thumb: Never compare floats with `==`. – Ferdinand Beyer Nov 29 '13 at 18:03
  • 1
    @Xymostech: that would make *no difference*. – Martijn Pieters Nov 29 '13 at 18:07
  • See http://stackoverflow.com/questions/1088216/whats-wrong-with-using-to-compare-floats-in-java . The question is about Java, but the same rules apply to floats in Python and collections containing floats in Python. – Ferdinand Beyer Nov 29 '13 at 18:09
  • 5
    Out of curiosity, what *are* the objects? Standard Python tuples wouldn't look like that -- the spacing is wrong -- and standard Python floats wouldn't show two decimals. So there's at least one nonstandard type involved. What are `type(innersearch)` and `type(innersearch[0])` (assuming the latter works)? – DSM Nov 29 '13 at 18:09
  • 1
    There coordinates, for turtle module. Sorry, I didn't realize that may have been salient; I was trying to shorten my questions to just the relevant information. – 5813 Nov 30 '13 at 02:44
  • 1
    @DaoWen: I'm interested in your explanation. Would you recommend I round the values before I compare them, and, if so, how? – 5813 Nov 30 '13 at 02:49
  • 2
    You can look at *[Floating point equality in python](http://stackoverflow.com/questions/4028889/floating-point-equality-in-python)* for some more info on how you should compare floating point numbers. – DaoWen Nov 30 '13 at 04:06
  • How did you get the -0 values in the first place? – Junuxx Dec 01 '13 at 17:48
  • The `-0.00` is just the way the module names the coordinates. – 5813 Dec 01 '13 at 17:58
  • @DaoWen, with the new information, any help? – 5813 Dec 01 '13 at 17:59
  • Knowing that these are `turtle.Vec2D` objects rather than native tuples provides a clue. Does `turtle.Vec2D` implement the equality operator? – Tim Pierce Dec 01 '13 at 18:32
  • 1
    Are you leaving anything out here? Are you really just comparing two Vec2Ds with two entries, or did you simplify that for the example? @qwrrty - Yes, they derive from Tuple and implement equality. – DaoWen Dec 02 '13 at 00:52
  • @5813: No, normally (with normal arithmetic or by initializing a Vec2D object) you don't get negative zero, only if you explicitly define it as such, So where exactly do innersearch and innersub come from? What is their repr()? – Junuxx Dec 02 '13 at 08:43
  • Thanks for all the help, guys, but I got it with the help of @user2357112, by rounding the values. – 5813 Dec 03 '13 at 12:46

1 Answers1

2

Two lists are considered equal if, and only if, both lists have the same length and each element in the first list compares equal to the corresponding element in the second. That's roughly:

def lists_equals(l1, l2):
    if len(l1) != len(l2):
        return False
    return all(a == b for (a, b) in zip(l1, l2))

An important thing to note is that equality semantics are not automatically defined for custom classes -- or rather, they default to identity. In the absence of an __eq__ method, two objects only compare as equal if they are the same object (a == b behaves exactly like a is b).

What this means is that if your lists contain instances of classes you wrote yourself and you want to be able to compare those lists, said classes must implement __eq__, or your comparisons won't work.

Max Noel
  • 8,810
  • 1
  • 27
  • 35