74

I was wondering if there was a function built into Python that can determine the distance between two rational numbers but without me telling it which number is larger. e.g.

>>>distance(6,3)
3
>>>distance(3,6)
3

Obviously I could write a simple definition to calculate which is larger and then just do a simple subtraction:

def distance(x, y):
    if x >= y:
        result = x - y
    else:
        result = y - x
    return result

but I'd rather not have to call a custom function like this. From my limited experience I've often found Python has a built in function or a module that does exactly what you want and quicker than your code does it. Hopefully someone can tell me there is a built in function that can do this.

Increasingly Idiotic
  • 5,700
  • 5
  • 35
  • 73
Rapid
  • 1,442
  • 1
  • 13
  • 25

10 Answers10

140

abs(x-y) will do exactly what you're looking for:

In [1]: abs(1-2)
Out[1]: 1

In [2]: abs(2-1)
Out[2]: 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 2
    But you'll face problem on sign while passing numbers dynamically. shared a working solution below. Please check – Siva S Nov 11 '19 at 16:18
30

Although abs(x - y) and equivalently abs(y - x) work, the following one-liners also work:

  • math.dist((x,), (y,)) (available in Python ≥3.8)

  • math.fabs(x - y)

  • max(x - y, y - x)

  • -min(x - y, y - x)

  • max(x, y) - min(x, y)

  • (x - y) * math.copysign(1, x - y), or equivalently (d := x - y) * math.copysign(1, d) in Python ≥3.8

  • functools.reduce(operator.sub, sorted([x, y], reverse=True))

All of these return the euclidean distance(x, y).

Asclepius
  • 57,944
  • 17
  • 167
  • 143
  • 2
    It might be useful to explain why one might choose one solution over another. From an outsider perspective, I would wonder "who cares?" if the shortest solution, `abs(x - y)` is correct. – michael_teter Apr 12 '22 at 19:46
9

Just use abs(x - y). This'll return the net difference between the two as a positive value, regardless of which value is larger.

Chris Heald
  • 61,439
  • 10
  • 123
  • 137
8

If you have an array, you can also use numpy.diff:

import numpy as np
a = [1,5,6,8]
np.diff(a)
Out: array([4, 1, 2])
Asclepius
  • 57,944
  • 17
  • 167
  • 143
G M
  • 20,759
  • 10
  • 81
  • 84
4

So simple just use abs((a) - (b)).

will work seamless without any additional care in signs(positive , negative)

def get_distance(p1,p2):
     return abs((p1) - (p2))

get_distance(0,2)
2

get_distance(0,2)
2

get_distance(-2,0)
2

get_distance(2,-1)
3

get_distance(-2,-1)
1
Siva S
  • 752
  • 6
  • 12
2

use this function.

its the same convention you wanted. using the simple abs feature of python.

also - sometimes the answers are so simple we miss them, its okay :)

>>> def distance(x,y):
    return abs(x-y)
Inbar Rose
  • 41,843
  • 24
  • 85
  • 131
1

This does not address the original question, but I thought I would expand on the answer zinturs gave. If you would like to determine the appropriately-signed distance between any two numbers, you could use a custom function like this:

import math

def distance(a, b):
    if (a == b):
        return 0
    elif (a < 0) and (b < 0) or (a > 0) and (b > 0):
        if (a < b):
            return (abs(abs(a) - abs(b)))
        else:
            return -(abs(abs(a) - abs(b)))
    else:
        return math.copysign((abs(a) + abs(b)),b)

print(distance(3,-5))  # -8

print(distance(-3,5))  #  8

print(distance(-3,-5)) #  2

print(distance(5,3))   # -2

print(distance(5,5))   #  0

print(distance(-5,3))  #  8

print(distance(5,-3))  # -8

Please share simpler or more pythonic approaches, if you have one.

phi
  • 313
  • 3
  • 4
  • 2
    same tests pass with : import math def distance(a, b): return (max(a, b) - min(a, b)) * (-1 if a > b else 1) – pansay Jul 20 '18 at 12:47
  • Surely what pansay has provided would be the best answer to this question? – arranjdavis Jan 21 '21 at 09:45
  • The appropriately signed distance between two numbers (if there is such a thing) is `b-a`. I find the code needlessly complex and the problem it solves is not defined. – Johannes Overmann Oct 05 '21 at 07:30
  • This is a ridiculous and pointless answer since `abs(a - b)` works for distance in all cases. It even returns negative distances sometimes which are invalid. – Asclepius Dec 12 '21 at 19:39
0

If you plan to use the signed distance calculation snippet posted by phi (like I did) and your b might have value 0, you probably want to fix the code as described below:

import math

def distance(a, b):
    if (a == b):
        return 0
    elif (a < 0) and (b < 0) or (a > 0) and (b >= 0): # fix: b >= 0 to cover case b == 0
        if (a < b):
            return (abs(abs(a) - abs(b)))
        else:
            return -(abs(abs(a) - abs(b)))
    else:
        return math.copysign((abs(a) + abs(b)),b)

The original snippet does not work correctly regarding sign when a > 0 and b == 0.

adp
  • 9
  • 3
-1

abs function is definitely not what you need as it is not calculating the distance. Try abs (-25+15) to see that it's not working. A distance between the numbers is 40 but the output will be 10. Because it's doing the math and then removing "minus" in front. I am using this custom function:


def distance(a, b):
    if (a < 0) and (b < 0) or (a > 0) and (b > 0):
        return abs( abs(a) - abs(b) )
    if (a < 0) and (b > 0) or (a > 0) and (b < 0):
        return abs( abs(a) + abs(b) )

print distance(-25, -15) print distance(25, -15) print distance(-25, 15) print distance(25, 15)

zinturis
  • 9
  • 2
  • 1
    `abs(-25 - 15) = abs(15 - -25) = 40`. I don't know why you used `abs(-25 + 15)` -- that's an incorrect use of `abs` in this context. As for distance, `def distance(a, b): return abs(a - b)`. – Asclepius Nov 15 '16 at 20:24
  • The question was about the distance. For instance, the distance between -25 and -15 is not 40 it is 10. – zinturis Nov 16 '16 at 16:20
  • 1
    And so what? Substituting `a` and `b` in `abs(a - b)` with -25 and -15 gives 10, not 40. In summary, `abs(a - b)` works for distance. It is noted in the first answer, and not in yours. – Asclepius Nov 25 '16 at 00:29
-6

You can try: a=[0,1,2,3,4,5,6,7,8,9];

[abs(x[1]-x[0]) for x in zip(a[1:],a[:-1])]