在Python中,如何找到整数中的位数?
当前回答
所有的数学。Log10的解会给你带来问题。
数学。Log10速度很快,但当你的数字大于999999999999997时就会出现问题。这是因为浮点数有太多的.9,导致结果四舍五入。
因此,为了获得最佳性能,对于较小的数字使用math.log,并且只使用超出math.log处理范围的len(str()):
def getIntegerPlaces(theNumber):
if theNumber <= 999999999999997:
return int(math.log10(theNumber)) + 1
else:
return len(str(theNumber))
其他回答
这个问题已经问了好几年了,但是我已经编写了一个基准测试,其中包含了几种计算整数长度的方法。
def libc_size(i):
return libc.snprintf(buf, 100, c_char_p(b'%i'), i) # equivalent to `return snprintf(buf, 100, "%i", i);`
def str_size(i):
return len(str(i)) # Length of `i` as a string
def math_size(i):
return 1 + math.floor(math.log10(i)) # 1 + floor of log10 of i
def exp_size(i):
return int("{:.5e}".format(i).split("e")[1]) + 1 # e.g. `1e10` -> `10` + 1 -> 11
def mod_size(i):
return len("%i" % i) # Uses string modulo instead of str(i)
def fmt_size(i):
return len("{0}".format(i)) # Same as above but str.format
(libc函数需要一些设置,我没有包括这些设置)
size_exp由Brian Preslopsky提供,size_str由GeekTantra提供,size_math由John La Rooy提供
以下是调查结果:
Time for libc size: 1.2204 μs
Time for string size: 309.41 ns
Time for math size: 329.54 ns
Time for exp size: 1.4902 μs
Time for mod size: 249.36 ns
Time for fmt size: 336.63 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.240835x)
+ math_size (1.321577x)
+ fmt_size (1.350007x)
+ libc_size (4.894290x)
+ exp_size (5.976219x)
(声明:函数在输入1到1,000,000上运行)
下面是sys的测试结果。Maxsize: 100000 to sys.maxsize:
Time for libc size: 1.4686 μs
Time for string size: 395.76 ns
Time for math size: 485.94 ns
Time for exp size: 1.6826 μs
Time for mod size: 364.25 ns
Time for fmt size: 453.06 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.086498x)
+ fmt_size (1.243817x)
+ math_size (1.334066x)
+ libc_size (4.031780x)
+ exp_size (4.619188x)
正如你所看到的,mod_size (len("%i" %i))是最快的,比使用str(i)略快,比其他方法快得多。
您可以使用以下解决方案:
n = input("Enter number: ")
print(len(n))
n = int(n)
计算w/o将整数转换为字符串的位数:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
如果您正在寻找一个不使用内置函数的解决方案。 唯一需要注意的是当你发送a = 000时。
def number_length(a: int) -> int:
length = 0
if a == 0:
return length + 1
else:
while a > 0:
a = a // 10
length += 1
return length
if __name__ == '__main__':
print(number_length(123)
assert number_length(10) == 2
assert number_length(0) == 1
assert number_length(256) == 3
assert number_length(4444) == 4
正如其他答案所示,使用log10会导致大n的错误结果,而使用len(str(…))或手动循环会导致大n的性能变慢。Jodag的答案提供了一个非常好的替代方案,它只适用于可能会使您的计算机崩溃的整数,但我们可以做得更好,甚至更快(对于n足够小的数学。Log2保证是准确的),避免使用对数,而是使用二进制:
def num_digits(n: int) -> int:
assert n > 0
i = int(0.30102999566398114 * (n.bit_length() - 1)) + 1
return (10 ** i <= n) + i
让我们来分析一下。首先是奇怪的n.bit_length()。这将以二进制形式计算长度:
assert 4 == (0b1111).bit_length()
assert 8 == (0b1011_1000).bit_length()
assert 9 == (0b1_1011_1000).bit_length()
与对数不同,这对于整数来说既快速又精确。结果是,这个结果正好是(log2(n)) + 1。为了单独得到地板(log2(n)),我们减去1,因此n.bit_length() - 1。
接下来,我们乘以0.30102999566398114。这相当于log10(2)稍微舍入。这利用了对数规则,以便从地板(log2(n))计算地板(log10(n))的估计值。
现在,您可能想知道我们在这一点上可能有多差,因为尽管0.30102999566398114 * log2(n) ~ log10(n),但对于floor(0.30102999566398114 * floor(log2(n))) ~ floor(log10(n)),情况并非如此。回想一下x - 1 < floor(x) <= x,我们可以做一些快速的计算:
log2(n) - 1 < floor(log2(n)) <= log2(n)
log10(n) - 0.30102999566398114 < 0.30102999566398114 * floor(log2(n)) <= log10(n)
floor(log10(n) - 0.30102999566398114) < floor(0.30102999566398114 * floor(log2(n))) <= floor(log10(n))
请注意,floor(log10(n) - 0.30102999566398114)至少是floor(log10(n)) - 1,这意味着我们与结果最多相差1。这是最后的修正,我们检查10 ** i <= n,当结果太小时导致额外的1 +,当结果刚刚好时导致0 +。
类似于Jodag的答案,这种方法实际上对非常非常大的n无效,大约在10 ** 2 ** 52左右,其中i的误差超过-1。然而,这种大小的整数可能会使您的计算机崩溃,所以这应该足够了。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 确定记录是否存在的最快方法
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if