我将如何设法将math.ceil一个数字分配给 10 的下一个最高幂?
# 0.04 -> 0.1
# 0.7 -> 1
# 1.1 -> 10
# 90 -> 100
# ...
Run Code Online (Sandbox Code Playgroud)
我目前的解决方案是一个检查输入数字范围的字典,但它是硬编码的,我更喜欢单行解决方案。也许我在这里错过了一个简单的数学技巧或相应的 numpy 函数?
jon*_*rpe 68
您可以使用math.ceilwithmath.log10来执行此操作:
>>> 10 ** math.ceil(math.log10(0.04))
0.1
>>> 10 ** math.ceil(math.log10(0.7))
1
>>> 10 ** math.ceil(math.log10(1.1))
10
>>> 10 ** math.ceil(math.log10(90))
100
Run Code Online (Sandbox Code Playgroud)
log10(n)为您提供x满足的解决方案10 ** x == n,因此如果您将x其四舍五入,它将为您提供下一个最高 10 次幂的指数。
注意,对于价值n在那里x已经是一个整数,则“的10次大功率”将是n:
>>> 10 ** math.ceil(math.log10(0.1))
0.1
>>> 10 ** math.ceil(math.log10(1))
1
>>> 10 ** math.ceil(math.log10(10))
10
Run Code Online (Sandbox Code Playgroud)
plu*_*ash 23
您的问题未详细说明,您需要退后一步并提出一些问题。
在另一个答案中,建议取对数,然后向上取整(天花板函数),然后取幂。
def nextpow10(n):
return 10 ** math.ceil(math.log10(n))
Run Code Online (Sandbox Code Playgroud)
不幸的是,这会导致舍入错误。首先 n 从它碰巧拥有的任何数据类型转换为双精度浮点数,可能会引入舍入误差,然后计算对数可能会在其内部计算和结果中引入更多的舍入误差。
因此,我很快就找到了一个给出错误结果的例子。
>>> import math
>>> from numpy import nextafter
>>> n = 1
>>> while (10 ** math.ceil(math.log10(nextafter(n,math.inf)))) > n:
... n *= 10
...
>>> n
10
>>> nextafter(n,math.inf)
10.000000000000002
>>> 10 ** math.ceil(math.log10(10.000000000000002))
10
Run Code Online (Sandbox Code Playgroud)
从理论上讲,它也有可能在另一个方向上失败,尽管这似乎更难激发。
因此,对于浮点数和整数的稳健解决方案,我们需要假设对数的值只是近似值,因此我们必须测试几种可能性。类似的东西
def nextpow10(n):
p = round(math.log10(n))
r = 10 ** p
if r < n:
r = 10 ** (p+1)
return r;
Run Code Online (Sandbox Code Playgroud)
我相信这段代码应该在合理的现实世界范围内为所有参数提供正确的结果。由于将它们转换为浮点数的问题,它会因非常小或非常大的非整数和非浮点类型而中断。Python 特殊情况下 log10 函数的整数参数试图防止溢出,但仍然有足够大的整数,由于舍入错误,可能会强制产生不正确的结果。
为了测试这两个实现,我使用了以下测试程序。
n = -323 # 10**-324 == 0
while n < 1000:
v = 10 ** n
if v != nextpow10(v): print(str(v)+" bad")
try:
v = min(nextafter(v,math.inf),v+1)
except:
v += 1
if v > nextpow10(v): print(str(v)+" bad")
n += 1
Run Code Online (Sandbox Code Playgroud)
这在幼稚的实现中发现了很多失败,但在改进的实现中没有。