[PYTHON] Tips: Comparison of the size of three values

How to get the number between two numbers?

If you're a program maker, it's unlikely that you won't use size comparison. Among them, it is common to judge "Is the value $ c $ between $ a $ and $ b $?".

When the magnitude relationship between $ a $ and $ b $ is unknown, how do you solve the above problem?

Method 1

The most sensible method is to first understand the magnitude relationship between $ a $ and $ b $, and then compare it with $ c $.

if a < b:
    a < c < b
else:
    b < c < a

Well, it's not very beautiful. I don't want to use 4 lines for this ...

Method 2

Looking at the above, we can see that $ c $ is between $ a $ and $ b $ if either $ b <c <a $ or $ a <c <b $ holds. In other words, if you call it as follows, it will fit in one line.

(a < c < b) or (b < c < a)

It's getting better. However, this also has $ a, b, c $ appearing once, and it feels a bit redundant. You can write it so beautifully in python, but in C you have to write it as follows.

((a < c) && (c < b)) || ((b < c) && (c < a))

After all, it's not beautiful ...

Method 3

So, I came up with a way to write as follows.

(a < c) ^ (b < c)

^ may not be used much, but it is an exclusive OR. Both are True, both are False when they are False, and True when the two are True and False.

However, this has its drawbacks. The above formula is synonymous with the following.

(a < c <= b) or (b < c <= a)

This cannot be done like ʻa <c <b by changing < to> or <= `.

By the way,

(a <= c) ^ (b <= c)
(a > c) ^ (b > c)

Two of

(a <= c < b) or (b <= c < a)

Is synonymous with

Method 4

I wondered if I could somehow do ʻa <c <b or ʻa <= c <= b, but I thought about it, but the following method may be the most elegant.

(a - c) * (b - c) < 0
(a - c) * (b - c) <= 0

The first line is ʻa <c <b and the second line is ʻa <= c <= b. If the value is large, it may be possible to take a sign function (although the calculation time is likely to be considerably slower).

Calculation time

I measured the calculation time of each method. The program used the following.

import time
import numpy as np

n = 100
number1 = np.random.rand(n)
number2 = np.random.rand(n)

t1 = time.time()
for j in range(10000):
    for i in range(n):
        if number1[i] < number2[i]:
            x = number1[i] < 0.5 < number2[i]
        else:
            x = number1[i] < 0.5 < number2[i]
t2 = time.time()
t = t2-t1
print(t)

t1 = time.time()
for j in range(10000):
    for i in range(n):
        x = (number1[i] < 0.5 < number2[i]) or (number1[i] < 0.5 < number2[i])
t2 = time.time()
t = t2-t1
print(t)

t1 = time.time()
for j in range(10000):
    for i in range(n):
        x = (number1[i] < 0.5) ^ (number2[i] < 0.5)
t2 = time.time()
t = t2-t1
print(t)

t1 = time.time()
for j in range(10000):
    for i in range(n):
        x = (number1[i] - 0.5) * (number2[i] - 0.5) < 0
t2 = time.time()
t = t2-t1
print(t)

Calculation result

Method Calculation time
Method 1 0.547s
Method 2 0.458s
Method 3 0.370s
Method 4 0.786s

……。 (a --c) * (b --c) <0 is the slowest result. What is slower than Method 1 ... Isn't it just beautiful?

I tried it several times, but the ranking did not change. Well, it seems that multiplication takes time after all. Another reason is that and and or have the characteristic of ignoring subsequent operations when False or True appears in the middle.

I'm disappointed that this is all, so I also checked the calculation of the entire numpy array.

import time
import numpy as np

n = 100
number1 = np.random.rand(n)
number2 = np.random.rand(n)

t1 = time.time()
for j in range(10000):
    x = ((number1 < 0.5) & ( 0.5 < number2)) | ((number1 < 0.5) & (0.5 < number2))
t2 = time.time()
t = t2-t1
print(t)

t1 = time.time()
for j in range(10000):
    x = (number1 < 0.5) ^ (number2 < 0.5)
t2 = time.time()
t = t2-t1
print(t)

t1 = time.time()
for j in range(10000):
    x = ((number1 - 0.5) * (number2 < 0.5) < 0)
t2 = time.time()
t = t2-t1
print(t)

You can't write ʻa <c <bin numpy. Also, since there is no and, or, it is necessary to use logical operations&and|`. The calculation time is as follows.

Method Calculation time
Method 2 0.037s
Method 3 0.017s
Method 4 0.031s

In this case, the result was that multiplication was faster. I managed to keep my face ...

Summary

To determine if c is between a and b, use the following equation.

** For one-by-one comparison **

## a < c < b or b < c <In the case of a
a < c < b or b < c < a
##When a ≤ c ≤ b or b ≤ c ≤ a
a <= c <= b or b <= c <= a
## a < c ≦ b or b <When c ≤ a
(a < c) ^ (b < c)
## a ≦ c < b or b ≦ c <In the case of a
(a > c) ^ (b > c)

** For numpy arrays **

## a < c < b or b < c <In the case of a
(a - c) * (b - c) < 0
##When a ≤ c ≤ b or b ≤ c ≤ a
(a - c) * (b - c) <= 0
## a < c ≦ b or b <When c ≤ a
(a < c) ^ (b < c)
## a ≦ c < b or b ≦ c <In the case of a
(a > c) ^ (b > c)

Recommended Posts

Tips: Comparison of the size of three values
Increase the UI size of MyPaint
About the size of matplotlib points
[pyqtgraph] Set the size ratio of the graph
Align the size of the colorbar with matplotlib
Visualize the boundary values of the multi-layer perceptron
Test & Debug Tips: Create a file of the specified size in Python
Change the font size of the legend in df.plot
Increase the font size of the graph with matplotlib
FAQ: Why is the comparison of numbers inconsistent?
Thorough comparison of three Python morphological analysis libraries
Find the sum of unique values with pandas crosstab
Get the size (number of elements) of UnionFind in Python
The beginning of cif2cell
Comparison of LDA implementations
Comparison of online classifiers
the zen of Python
Reduction of slug size
The story of sys.path.append ()
Comparison of fitting programs
Revenge of the Types: Revenge of types
I tried the accuracy of three Stirling's approximations in python
Pepper decides the winner by measuring the size of the audience's applause
[python] plot the values ​​before and after the conversion of yeojohnson conversion
[Python] Calculate the angle consisting of three points on the coordinates
[Tips] Problems and solutions in the development of python + kivy
Find the average / standard deviation of the brightness values in the image