在Python中,如何找到整数中的位数?
当前回答
>>> a=12345
>>> a.__str__().__len__()
5
其他回答
这个问题已经问了好几年了,但是我已经编写了一个基准测试,其中包含了几种计算整数长度的方法。
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)略快,比其他方法快得多。
正如其他答案所示,使用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。然而,这种大小的整数可能会使您的计算机崩溃,所以这应该足够了。
不需要转换为字符串
import math
digits = int(math.log10(n))+1
也可以处理0和负数
import math
if n > 0:
digits = int(math.log10(n))+1
elif n == 0:
digits = 1
else:
digits = int(math.log10(-n))+2 # +1 if you don't count the '-'
你可能想把它放在一个函数中:)
以下是一些基准测试。len(str())对于非常小的数字已经落后了
timeit math.log10(2**8)
1000000 loops, best of 3: 746 ns per loop
timeit len(str(2**8))
1000000 loops, best of 3: 1.1 µs per loop
timeit math.log10(2**100)
1000000 loops, best of 3: 775 ns per loop
timeit len(str(2**100))
100000 loops, best of 3: 3.2 µs per loop
timeit math.log10(2**10000)
1000000 loops, best of 3: 844 ns per loop
timeit len(str(2**10000))
100 loops, best of 3: 10.3 ms per loop
假设您要求的是可以存储在整数中的最大数字,则该值与实现有关。我建议你在使用python时不要这样想。在任何情况下,相当大的值都可以存储在python 'integer'中。记住,Python使用鸭子类型!
编辑: 我在澄清提问者想要数字数之前给出了我的答案。就此而言,我同意公认答案所建议的方法。没什么可补充的了!
科学记数法格式,去掉指数:
int("{:.5e}".format(1000000).split("e")[1]) + 1
我不知道速度如何,但很简单。
请注意小数点后的有效数位数(“5”在”。如果5e”将科学记数法的小数部分舍入到另一个数字,则可能会出现问题。我把它设得任意大,但可以反映出你所知道的最大数字的长度。
推荐文章
- Python 3.7数据类中的类继承
- 如何在PyTorch中初始化权重?
- 计数唯一的值在一列熊猫数据框架像在Qlik?
- 使用Pandas将列转换为行
- 从matplotlib中的颜色映射中获取单个颜色
- 将Pandas或Numpy Nan替换为None以用于MysqlDB
- 使用pandas对同一列进行多个聚合
- 使用Python解析HTML
- django MultiValueDictKeyError错误,我如何处理它
- 如何在for循环期间修改列表条目?
- 我如何在Django中创建一个鼻涕虫?
- 没有名为'django.core.urlresolvers'的模块
- 蟒蛇导出环境文件
- Django - makemigrations -未检测到任何更改
- SQLAlchemy:引擎、连接和会话差异