10

I am trying to see if the calculated distance between two points is smaller than a given radius like this:

if distance(lat1, long1, lat2, long2) < radius:
      print "Distance: %s Radius: %s" % (distance(lat1, long1, lat2, long2), radius)

Here distance would effectively return a float and radius is an int.

I do know that I should not compare floats directly and that I should compare with a threshold. Given that, is there a better way to check if a float is less than an int (or another float).

Update This comparison seems to be ok from all of the replies. But I did observe this:

>>> 1.2000000000000001 > 1.2
True
>>> 1.20000000000000001 > 1.2
False

Isn't this a problem? I am using Python 2.6.7 on Mac

ACC
  • 2,488
  • 6
  • 35
  • 61
  • 2
    You shouldn't, in general, compare floats for *equality* without some care, but comparing floats for relativity (> or <) is perfectly fine. – Russell Borogove Apr 05 '12 at 23:02
  • Your update is due to [precision errors](http://docs.python.org/tutorial/floatingpoint.html) - they are a fact of computing, and shouldn't matter to you in 99.9% of cases as they difference is too small to care about. If they do, look into the [decimal module](http://docs.python.org/library/decimal.html). – Gareth Latty Apr 05 '12 at 23:14
  • @Lattyware - They matter in comparisons. See the link in my answer below. Floats are tricky. It's wrong to think they are easily compared. http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm – 01100110 Apr 05 '12 at 23:45
  • What is your definition of matter? In most cases the answer being wrong due to ``0.0000000001`` really won't matter. There are some cases (e.g: ``while not x == 0.9:``, ``x += 0.3``) but these can be handled by doing more sane checks (``<`` in this case). In any other case, it'll be caught on the next loop or the error won't be an issue as it's too small. – Gareth Latty Apr 05 '12 at 23:50

1 Answers1

18

Just compare them directly, there is no harm in that at all.

Python handles comparing numbers of different types perfectly well:

>>> type(1.1)
<class 'float'>
>>> type(1)
<class 'int'>
>>> 1.1 > 1
True
>>> 1.1 < 1
False
>>> 1 < 2
True
>>> 2.2 == 2.2
True
>>> 2 == 2.2
False
>>> 1.6 < 2
True
>>> 1.6 > 2
False
>>> 1.6 == 2
False

Python is duck typed, so in general you shouldn't worry about types directly, just if they can work in the way you need.

There could be some issues with comparing floats for equality with other floats due to precision errors:

>>> 0.3+0.3+0.3 == 0.9
False
>>> 0.3+0.3+0.3
0.8999999999999999

But in comparing to ints and/or < or > operations, you shouldn't worry.

In your update, we can use the decimal module to show the cause:

>>> Decimal(1.2000000000000001)
Decimal('1.20000000000000017763568394002504646778106689453125')
>>> Decimal(1.20000000000000001)
Decimal('1.1999999999999999555910790149937383830547332763671875')

But does this really matter? It's an inherent problem with floating point numbers, but only matters where you need really high precision.

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • Regarding your last point: This is why some Python IDEs will warn you when you compare float expression for equality. It is better to use something like numpy's `isclose` instead of directly comparing. – cadolphs Nov 19 '16 at 01:29
  • 1
    @antonagestam "At all" is probably poorly worded, "directly" is probably more accurate. – Gareth Latty Mar 27 '20 at 12:22
  • Comparing ints and floats can also lead to problems, don't do this! – knk Sep 07 '20 at 16:28