1

I'm writing a code that will be called several times and I was wondering if there was something faster (computationally wise) than this:

maximum = max(a, b)  # a and b are integers
minimum = min(a, b)

The code works but I guess once I called max we are wasting in a way computational power by calling min. I tried to look at the problem on the internet but I'm having trouble putting words on it.

  • What are the datatypes of `a` and `b`, and how large are they? If they're just integers, the "wasted" computational power is so infinitesimal as to be zero for all intents and purposes. Your code is fine. – MattDMo Mar 30 '22 at 15:48
  • `min(a, b)` only returns the _smaller of `a` and `b`_. Similar for `max(a, b)`. You could simply do `maximum, minimum = if a > b then a, b else b, a` If you want something that computes the max and min of an _iterable_ in one pass instead of doing two by calling `max` and `min` separately, you're probably better off doing the latter since the builtin uses C code to do the looping – Pranav Hosangadi Mar 30 '22 at 15:50
  • 1
    ^ According to a quick test, the builtin `min` and `max` are ~1.5x faster than looping over a `10_000_000`-long list. – Pranav Hosangadi Mar 30 '22 at 15:59
  • 2
    @PranavHosangadi Your suggested ternary style is syntactically flawed – DarkKnight Mar 30 '22 at 16:13
  • @python_user no it doesn't, my problem is with integers (sorry I initially didn't mention it) – FluidMechanics Potential Flows Mar 30 '22 at 16:20
  • If can keep `a` and `b` as names, I'd rather assume `a` is min and `b` is max and just use `if a > b: a, b = b, a` to swap their values. – norok2 Mar 31 '22 at 07:18

4 Answers4

4

This would rather depend on what data types a and b are. If they are simple types (e.g., numeric) then:

if a > b:
  maximum, minimum = a, b
else:
  maximum, minimum = b, a

...might be faster than calling the min and max functions.

Or, if you like one-liners:

maximum, minimum = (a, b) if a > b else (b, a)
DarkKnight
  • 19,739
  • 3
  • 6
  • 22
  • Funnily enough, the one-liner looks like it's taking longer (cf. the response to my own post). But your method is by far the quickest, so cheers! – FluidMechanics Potential Flows Mar 30 '22 at 16:25
  • @FluidMechanicsPotentialFlows I am not a proponent of one-liners. It's something of a fad amongst Python coders. Keep it simple and readable is my motto. If it takes a few nanoseconds longer at runtime then so be it but think also about the amount of time it might take for someone maintaining your code to try to unravel and fix/modify it – DarkKnight Mar 30 '22 at 16:31
  • I mean the one liner is longer anyway so the one liner is less readable AND longer. So it goes your way I guess. I also don't really like one-liners. – FluidMechanics Potential Flows Mar 30 '22 at 16:32
  • Even if `a` and `b` are iterables, `max(a, b)` just returns the greater of the two – Pranav Hosangadi Mar 30 '22 at 19:26
2

If you are worried about computational power here it should not be a problem. No matter what you would need to define two different variables, maximum and minimum, so the way you did it is fine. If you really do not want to use min, then something like this could work but it is already more complex than what you did:

if max(a, b) == a:
    maximum = a
    minimum = b
else:
    maximum = b
    minimum = a
1

Mathematically min(a,b) is the same as a+b-max(a,b). Whether this is an improvement is debatable.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

I've ran this code with your suggestions (all very clever ones, thank you!!) to try and see what's faster. The differences are actually quite impressive:

import time

def whosfaster(a, b):
    start_time = time.time()
    maximum = max(a, b)
    minimum = min(a, b)
    method0 = time.time() - start_time


    start_time = time.time()
    if a > b:
        maximum, minimum = a, b
    else:
        maximum, minimum = b, a
    method1 = time.time() - start_time

    start_time = time.time()
    maximum, minimum = max(a, b), min(a, b)
    method2 = time.time() - start_time

    start_time = time.time()
    maximum, minimum = (a, b) if a > b else (b, a)
    method3 = time.time() - start_time

    start_time = time.time()
    if max(a, b) == a:
        maximum = a
        minimum = b
    else:
        maximum = b
        minimum = a
    method4 = time.time() - start_time

    return maximum, minimum, method0, method1, method2, method3, method4

total = [0, 0, 0, 0, 0]
for a in range(1, 5000):
    for b in range(1, 5000):
        maximum, minimum, method0, method1, method2, method3, method4 = whosfaster(a, b)
        total[0] += method0
        total[1] += method1
        total[2] += method2
        total[3] += method3
        total[4] += method4

print(total)

The results I obtained are:

    Run number 1 : 
[7.562410593032837, 2.4336302280426025, 7.17744255065918, 3.160186529159546, 5.583981037139893]
    Run number 2 but my laptop was on battery saver mode :
[12.757804155349731, 4.507119178771973, 13.357162237167358, 5.251198768615723, 8.934610605239868]

If someone wants to run it on their end to compare, you're welcome to do so, my laptop isn't the fastest!!

EDIT : I didn't really know how to implement Mark Ransom's answer into practice, so I didn't try it. Feel welcome to edit my post and change my code and to rerun it on your hand if you know how to do so.