math.ceil
来将数字分配给下一个最高的10的幂次方?# 0.04 -> 0.1
# 0.7 -> 1
# 1.1 -> 10
# 90 -> 100
# ...
我目前的解决方案是一个字典,它检查输入数字的范围,但它是硬编码的,我更喜欢一个一行的解决方案。也许我在这里错过了一个简单的数学技巧或相应的numpy函数吗?
你可以使用math.ceil
和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
,"下一个最高的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
10 ** math.ceil(math.log10(1)) == 1
,这不是“下一个最高的幂”。 - Cireo你的问题没有给出足够的信息,需要回过头来询问一些问题。
另一个答案建议取对数,然后向上取整(ceiling函数),最后求指数。
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
...
>>> n
10
>>> 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 == 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
这个测试发现了天真实现中的许多失败,但在改进后的实现中没有发现任何失败。
round
而不是 math.ceil
?这会引入许多不必要的情况,其中 r < n
为真,因此需要执行额外的工作。 - a_guest看起来你想要的是比当前数小的下一个10的次幂......这里有一种使用纯数学和递归而不使用对数的方法。
def ceiling10(x):
if (x > 10):
return ceiling10(x / 10) * 10
else:
if (x <= 1):
return ceiling10(10 * x) / 10
else:
return 10
for x in [1 / 1235, 0.5, 1, 3, 10, 125, 12345]:
print(x, ceiling10(x))
对于已经以字符串格式出现的大整数,有一个特定的快捷方式可用:
而不必先将其转换为整数,或运行它通过 log()/ceiling()
函数,或执行任何类型的模数数学运算,下一个最大的10的幂次方就是:
10 ** length(big_int_str_var)
——以下:第一个生成格式化的10次幂字符串,第二个是数字
echo 23958699683561808518065081866850688652086158016508618152865101851111111111111 |
tee >( gpaste | gcat -n >&2; ) | gcat - |
python3 -c '\
import sys; [ print("1"+"0"*len(_.strip("\n"))) for _ in sys.stdin ]'
or '... [ print( 10 ** len(_.strip("\n"))) for _ in sys.stdin ]'
1 23958699683561808518065081866850688652086158016508618152865101851111111111111
1 100000000000000000000000000000000000000000000000000000000000000000000000000000
看看这个!
>>> i = 0.04123
>>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]]))
0.04123 0.1
>>> i = 0.712
>>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]]))
0.712 1
>>> i = 1.1
>>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]]))
1.1 10
>>> i = 90
>>> print i, 10 ** len(str(int(i))) if int(i) > 1 else 10 if i > 1.0 else 1 if i > 0.1 else 10 ** (1 - min([("%.100f" % i).replace('.', '').index(k) for k in [str(j) for j in xrange(1, 10) if str(j) in "%.100f" % i]]))
90 100
这段代码基于十的幂原理,使用 len(str(int(float_number)))
。
有四种情况:
int(i) > 1
。
Float
数字 - 转换为 int
,然后从中获取字符串 str()
,将会给我们一个恰好符合要求的 string
的 length
。因此,对于输入 i > 1.0
的第一部分,它是这个长度的十的幂。
i > 1.0
和 i > 0.1
时,分别等于 10
和 1
。i < 0.1
时:这里,十应该是负数幂。为了获得逗号后的第一个非零元素,我使用了这样的结构:("%.100f" % i).replace('.', '').index(k)
,其中 k 在区间 [1:10]
上运行。然后,取结果列表的最小值。并减去一,这是第一个零,应该被计算。此外,在这里标准的 Python 的 index()
可能会崩溃,如果它在区间 [1:10]
中找不到至少一个非零元素,这就是为什么最后我必须通过出现次数来“过滤”列表:if str(j) in "%.100f" % i
。此外,为了获得更深入的精度 - 可以采用不同的 %.100f
。我认为最简单的方法是:
import math
number = int(input('Enter a number: '))
next_pow_ten = round(10 ** math.ceil(math.log10(number)))
print(str(10) + ' power ' + str(round(math.log10(number))) + ' = '\
+ str(next_pow_ten))
希望这能帮到你。
y = math.ceil(x)
z = y + (10 - (y % 10))
像这样的东西吗?我随口说了一下,但在终端中试了几个数字后它就起作用了。
10
及以上的数字,这将需要使用例如log10
的内容。 - jonrsharpe