Elburz Sorkhabi
Elburz Sorkhabi

Reputation: 37

"Quantize" when rounding numbers Python 3.2

I'm trying to find a way to snap or quantize numbers to specific values after a math operation and don't really know the best way to approach the problem.

A specific example:

I have a list of numbers that I want to be my master numbers - 5, 10, 30, 60, 120, 180

I have a list of numbers that are currently inputted - 10, 20, 60, 120

Now I want to multiply all the inputted numbers by 2, and have them snap (or quantize/get rounded to) the nearest of my master numbers.

So a number like 10, once multiplied by two, I'd like to have it snap to 30. I dont think it's a big problem for the top or bottom because I think I can use math.ceil and math.floor to contain the ends. Similarly I'd like 20 to be rounded to 30 as well (20*2=40, rounded down as 30 is closer than 60).

I saw a similar question in regards to rounding to 10s, 100s, etc, but can't really figure out how to apply the answer there, as I'm still relatively new! : )

Upvotes: 1

Views: 1296

Answers (2)

user4815162342
user4815162342

Reputation: 154866

Use the bisect module to quickly pinpoint the desired quantity:

import bisect

def quantize(num, quant):
    mids = [(quant[i] + quant[i + 1]) / 2.0
            for i in xrange(len(quant) - 1)]
    ind = bisect.bisect_right(mids, num)
    return quant[ind]

quantnum = [5, 10, 30, 60, 120, 180]

inputnum = [10, 20, 60, 120]

for n in inputnum:
    print quantize(2 * n, quantnum)

# Output:
#30
#30
#120
#180

Midpoints are rounded to the larger quantity; change bisect_right to bisect_left to round to the smaller one instead.

For simplicity, this implementation recreates the mids list each time it is called. An efficient implementation would reuse the midpoints, and would run with O(log n) worst-case complexity.

Upvotes: 3

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250881

For element x of input find the absolute difference of x*2 with each element of master and x*2, and then the minimum of that new list will be the rounded number.

for ex. for for 20 from the input list, the list of absolute differences is going to be:

[abs(5-40),abs(10-40),abs(30-40),abs(60-40),abs(120-40),abs(180-40)]

which results in [35,30,10,20,80,140], and the minimum difference came for 3rd element ,i.e 30 of master list

In [14]: inp=[10, 20, 60, 120,17,27,50]

In [15]: master=[5, 10, 30, 60, 120, 180]

In [16]: [min(master,key=lambda y:abs(y-x*2)) for x in inp]
Out[16]: [10, 30, 120, 180, 30, 60, 120]

Upvotes: 2

Related Questions