我想知道如何将 numpy 中的数字舍入到上限或下限阈值,该阈值是预定义步长的函数。希望以更清晰的方式说明,如果我有数字 123 且步长等于 50,我需要将 123 舍入到最接近的 150 或 100,在本例中为 100。我得出了下面的函数,它可以完成这项工作但我想知道是否有更好、更简洁的方法来做到这一点。
提前致谢,
保罗
def getRoundedThresholdv1(a, MinClip):
import numpy as np
import math
digits = int(math.log10(MinClip))+1
b = np.round(a, -digits)
if b > a: # rounded-up
c = b - MinClip
UpLow = np.array((b,c))
else: # rounded-down
c = b + MinClip
UpLow = np.array((c,b))
AbsDelta = np.abs(a - UpLow)
return UpLow[AbsDelta.argmin()]
getRoundedThresholdv1(143, 50)
pb360 的解决方案要好得多,使用 python3 中内置 round 的第二个参数。
我认为你不需要
numpy
:
def getRoundedThresholdv1(a, MinClip):
return round(float(a) / MinClip) * MinClip
这里
a
是单个数字,如果你想向量化这个函数,你只需要将 round
替换为 np.round
,将 float(a)
替换为 np.array(a, dtype=float)
总结:这是正确的方法,最上面的答案有不起作用的情况:
def round_step_size(quantity: Union[float, Decimal], step_size: Union[float, Decimal]) -> float:
"""Rounds a given quantity to a specific step size
:param quantity: required
:param step_size: required
:return: decimal
"""
precision: int = int(round(-math.log(step_size, 10), 0))
return float(round(quantity, precision))
我的声誉太低,无法对 Ruggero Turra 的最佳答案发表评论并指出问题。然而,它也有不起作用的情况,例如:
def getRoundedThresholdv1(a, MinClip):
return round(float(a) / MinClip) * MinClip
getRoundedThresholdv1(quantity=13.200000000000001, step_size=0.0001)
无论使用 numpy 还是标准库回合,都会返回 13.200000000000001。我什至通过对该功能进行压力测试都没有发现这一点。它只是在生产代码中使用它时出现并抛出错误。
注意这个答案的全部功劳来自一个开源 github 存储库,这不是我发现的这里
请注意,在 Ruggero Turra 中,他的答案四舍五入到最接近的偶数。含义:
round()
这可能不是你所期望的。
如果您想要“经典”舍入,您可以使用此函数,它支持标量和 Numpy 数组:
a= 0.5
round(a)
Out: 0
import Numpy as np
def getRoundedThresholdv1(a, MinClip):
scaled = a/MinClip
return np.where(scaled % 1 >= 0.5, np.ceil(scaled), np.floor(scaled))*MinClip
。它要求您定义步骤数组。
digitize
将会 digitize
您对下一步的价值。因此,为了以“经典”方式进行舍入,我们需要一个中间步骤。您可以使用这个:
ceil
然后你可以这样称呼它:
import Numpy as np
def getRoundedThresholdv1(a, MinClipBins):
intermediate = (MinClipBins[1:] + MinClipBins[:-1])/2
return MinClipBins[np.digitize(a, intermediate)]
这给出了:
bins = np.array([0, 50, 100, 150])
test1 = getRoundedThresholdv1(74, bins)
test2 = getRoundedThresholdv1(125, bins)