如何设法将math.ceil
数字分配给下一个最高幂10?
# 0.04->0.1# 0.7 ->1# 1.1 ->10# 90->100# ...
我当前的解决方案是检查输入数字范围的字典,但是它是硬编码的,因此我希望使用单线解决方案。也许我在这里错过了一个简单的数学技巧或相应的numpy函数?
您可以使用math.ceil
with math.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
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
您的问题未指定,您需要退后一步并提出一些问题。
您输入的是什么类型?
您想要什么类型的输出?
对于小于1的结果,您想精确舍入到什么?您是否想要10的实际乘方或10的乘方的浮点近似值?您知道不能完全以浮点数表示10的负幂吗?现在让我们假设您想要10的幂的浮点近似值。
如果输入正好是10的幂(或者是10的幂的最接近的浮点近似值),则输出应该与输入相同吗?还是应该成为10的下一个幂?“ 10-> 10”或“ 10-> 100”?现在假设前者。
您的输入值可以是所讨论类型的任何可能的值吗?还是他们更受约束。
在另一个答案中,建议采用对数,然后取整(上限函数),然后取幂。
def nextpow10(n): return 10 ** math.ceil(math.log10(n))
不幸的是,这遭受了舍入误差。首先,将n恰巧从任何数据类型转换为双精度浮点数,这可能会导致舍入误差,然后计算对数,可能会在其内部计算和结果中引入更多舍入误差。
因此,很快就找到了给出错误结果的示例。
>>> import math>>> from numpy import nextafter>>> n = 1>>> while (10 ** math.ceil(math.log10(nextafter(n,math.inf)))) > n:... n *= 10... >>> n10>>> nextafter(n,math.inf)10.000000000000002>>> 10 ** math.ceil(math.log10(10.000000000000002))10
从理论上讲,它也有可能在另一个方向上失败,尽管这似乎很难引起。
因此,对于浮点数和整数的可靠解决方案,我们需要假定对数的值仅是近似值,因此我们必须测试几种可能性。遵循以下原则
def nextpow10(n): p = round(math.log10(n)) r = 10 ** p if r < n: r = 10 ** (p+1) return r;
我相信这段代码应该在合理的现实世界范围内为所有参数给出正确的结果。由于将非整数和非浮点类型转换为浮点的问题,它会中断非常少或非常多的非整数和非浮点类型。为了防止溢出,Python特殊情况下使用log10函数的整数参数来防止溢出,但是仍然具有足够大的整数,由于舍入错误,可能会强制产生不正确的结果。
为了测试这两种实现,我使用了以下测试程序。
n = -323 # 10**-324 == 0while n < 10: 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
这在幼稚的实现中发现很多失败,而在改进的实现中没有发现失败。