[英]Fast and precise nearest step floating point ceiling/flooring without Decimal.quantize
The following function is supposed to ceil the given number to the nearest step:以下 function 应该将给定数字上限到最近的步骤:
def ceil_step(x, step):
return math.ceil(x / step) * step
This works well... until it does not:这很好用......直到它没有:
print(ceil_step(1000.365, 0.01)) # 1000.37
print(ceil_step(1000.369, 0.01)) # 1000.37
print(ceil_step(1000.370, 0.01)) # 1000.37
print(ceil_step(1000.371, 0.01)) # 1000.38
print(ceil_step(10000.365, 0.01)) # 10000.37
print(ceil_step(10000.369, 0.01)) # 10000.37
print(ceil_step(10000.370, 0.01)) # 10000.380000000001
print(ceil_step(10000.371, 0.01)) # 10000.380000000001
A working implementation would be:一个可行的实现是:
def ceil_step(x, step):
return Decimal(str(x)).quantize(Decimal(str(step)), rounding=ROUND_CEILING)
Unfortunately, I cannot use it because I am writing Numba-accelerated Python code.不幸的是,我无法使用它,因为我正在编写 Numba 加速的 Python 代码。 Therefore, my question: Is there a way to implement the
ceil_step
(and analogously floor_step
) function such that it only uses basic floating point operations or Numba-supported function calls and produces reliable results?因此,我的问题是:有没有办法实现
ceil_step
(以及类似floor_step
) function 以便它只使用基本的浮点运算或 Numba 支持的 function 调用并产生可靠的结果?
For now, I have settled with the following function:目前,我已经解决了以下 function:
def round_step(x, step, method=-1):
eps = np.finfo(np.float64).eps
digits = math.ceil(-np.log10(step))
return round(math.ceil(x * (1 - eps) / step) * step, digits)
The multiplication with (1 - eps)
makes sure (hopefully!) that math.ceil
does not overshoot.与
(1 - eps)
的乘法确保(希望如此!) math.ceil
不会过冲。 The round
is necessary to get rid of stuff like ...0000000001
.这
round
对于摆脱...0000000001
之类的东西是必要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.