ChatGPT解决这个技术问题 Extra ChatGPT

如何查找整数中的数字长度?

在 Python 中,如何求整数的位数?

我不明白你的问题。你是说整数的大小吗?你想找到位数吗?请说清楚。

A
Alois Mahdal

如果您希望整数的长度与整数中的位数一样,您始终可以将其转换为字符串,如 str(133) 并找到它的长度,如 len(str(123))


当然,如果您正在寻找位数,这将产生一个对于负数来说太大的结果,因为它会计算负号。
嘿,这是一个缓慢的解决方案。我做了一个随机 6 位数字的阶乘,并找到了它的长度。此方法耗时 95.891 秒。而 Math.log10 方法只用了 7.486343383789062e-05 秒,大约快 1501388 倍!
这不仅速度慢,而且会消耗更多的内存,并且可能会导致大量问题。请改用 Math.log10
len(str(0)) 为 1
但是'0'中的位数不等于1吗?
J
John La Rooy

不转换为字符串

import math
digits = int(math.log10(n))+1

同时处理零和负数

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

为此使用 log10 是数学家的解决方案;使用 len(str()) 是程序员的解决方案,而且更清晰、更简单。
@Glenn:我当然希望你不是暗示这是一个糟糕的解决方案。程序员的天真 O(log10 n) 解决方案在临时的原型代码中运行良好——但我更愿意在生产代码或公共 API 中看到数学家优雅的 O(1) 解决方案。 +1 咬人。
你好!我遇到了一些奇怪的事情,你们中的任何人都可以解释一下为什么 int(math.log10(x)) +1 for 99999999999999999999999999999999999999999999999999999999999999999999999 (71 Nines) 返回 72 吗?我认为我可以依赖 log10 方法,但我必须使用 len(str(x)) 代替:(
我相信我知道这种奇怪行为的原因,这是由于浮点不准确,例如。 math.log10(999999999999999) 等于 14.999999999999998,因此 int(math.log10(999999999999999)) 变为 14。但是 math.log10(9999999999999999) 等于 16.0。也许使用 round 可以解决这个问题。
再进行一些测试:在 10**12 下,len(str(n)) 是最快的。在此之上,纯 log10 始终是最快的,但在 10**15 之上,它是不正确的。只有在 10**100 左右,我的解决方案(带有 10**b 检查的 ~log10)才开始击败 len(str(n))。总之,使用 len(str(n))
C
Calvintwr

所有 math.log10 解决方案都会给您带来问题。

math.log10 速度很快,但是当您的数字大于 999999999999997 时会出现问题。这是因为浮点数的 0.9 太多,导致结果四舍五入。

解决方案是对高于该阈值的数字使用 while 计数器方法。

为了使这更快,创建 10^16、10^17 等等,并作为变量存储在列表中。这样,它就像一个表格查找。

def getIntegerPlaces(theNumber):
    if theNumber <= 999999999999997:
        return int(math.log10(theNumber)) + 1
    else:
        counter = 15
        while theNumber >= 10**counter:
            counter += 1
        return counter

谢谢你。这是 math.log10 的一个很好的反例。有趣的是,二进制表示如何翻转数值,给出数学上不正确的结果。
那么 len(str(num)) 会更好
@Vighnesh Raut:而且幅度变慢
“依赖浮点运算给出精确结果是很危险的”- 核心 Python 开发团队成员 Mark Dickinson bugs.python.org/issue3724
def getIntegerPlaces(theNumber): if theNumber <= 999999999999997: return int(math.log10(abs(theNumber))) + 1 else: return int(math.log10(abs(theNumber)))
J
Jack Moody

自从提出这个问题以来已经有好几年了,但我已经编译了几种方法的基准来计算整数的长度。

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 - 100000sys.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) 稍快,并且比其他方法快得多。


您确实应该包括 libc 设置,libc = ctyle.CDLL('libc.so.6', use_errno=True)(猜测就是这样)。它不适用于大于 sys.maxsize 的数字,因为浮点数不能“非常大”。因此,任何高于此的数字,我想您都被其中一种较慢的方法所困扰。
A
Alex Martelli

Python 2.* int 占用 4 或 8 个字节(32 或 64 位),具体取决于您的 Python 版本。 sys.maxint2**31-1 表示 32 位整数,2**63-1 表示 64 位整数)会告诉您两种可能性中的哪一种。

在 Python 3 中,int(如 Python 2 中的 long)可以采用任意大小,直至可用内存量; sys.getsizeof 为您提供了任何给定值的良好指示,尽管它确实也计算了一些固定开销:

>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28

如果正如其他答案所暗示的那样,您正在考虑整数值的某种字符串表示形式,那么只需采用该表示形式的 len,无论是以 10 为底还是其他形式!


抱歉,这个答案被减去了。它提供了丰富的信息并且对问题的合理点(如果它只是更具体地说明需要哪个'len')。 +1
这看起来很有趣,但不确定如何提取长度
B
BiGYaN

设数字为 n,则 n 中的位数由下式给出:

math.floor(math.log10(n))+1

请注意,这将给出 +ve 整数 < 的正确答案。 10e15。除此之外,math.log10 的返回类型的精度限制开始起作用,答案可能会偏离 1。除此之外,我会简单地使用 len(str(n));这需要 O(log(n)) 时间,这与迭代 10 的幂相同。

感谢@SetiVolkylany 让我注意到这个限制。令人惊讶的是,看似正确的解决方案在实施细节中却存在警告。


如果 n 超出范围 [-999999999999997, 999999999999997],它将不起作用
@SetiVolkylany,我对 python2.7 和 3.5 进行了 50 位测试。只需执行 assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))]
尝试使用 Python2.7 或 Python3.5 >>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0。看我的回答stackoverflow.com/a/42736085/6003870
o
odradek

好吧,如果不转换为字符串,我会执行以下操作:

def lenDigits(x): 
    """
    Assumes int(x)
    """

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

极简递归 FTW


您将达到大数的递归限制。
C
Community

正如亲爱的用户@Calvintwr 所提到的,函数 math.log10 在 [-999999999999997, 9999999999999997] 范围之外的数字中存在问题,我们会遇到浮点错误。我在 JavaScript(Google V8 和 NodeJS)和 C(GNU GCC 编译器)中遇到了这个问题,所以这里不可能使用 'purely mathematically' 解决方案。

基于此 gistanswer 亲爱的用户 @Calvintwr

import math


def get_count_digits(number: int):
    """Return number of digits in a number."""

    if number == 0:
        return 1

    number = abs(number)

    if number <= 999999999999997:
        return math.floor(math.log10(number)) + 1

    count = 0
    while number:
        count += 1
        number //= 10
    return count

我对长度不超过 20(含)的数字进行了测试,没问题。它必须足够,因为 64 位系统上的最大长度整数是 19 (len(str(sys.maxsize)) == 19)。

assert get_count_digits(-99999999999999999999) == 20
assert get_count_digits(-10000000000000000000) == 20
assert get_count_digits(-9999999999999999999) == 19
assert get_count_digits(-1000000000000000000) == 19
assert get_count_digits(-999999999999999999) == 18
assert get_count_digits(-100000000000000000) == 18
assert get_count_digits(-99999999999999999) == 17
assert get_count_digits(-10000000000000000) == 17
assert get_count_digits(-9999999999999999) == 16
assert get_count_digits(-1000000000000000) == 16
assert get_count_digits(-999999999999999) == 15
assert get_count_digits(-100000000000000) == 15
assert get_count_digits(-99999999999999) == 14
assert get_count_digits(-10000000000000) == 14
assert get_count_digits(-9999999999999) == 13
assert get_count_digits(-1000000000000) == 13
assert get_count_digits(-999999999999) == 12
assert get_count_digits(-100000000000) == 12
assert get_count_digits(-99999999999) == 11
assert get_count_digits(-10000000000) == 11
assert get_count_digits(-9999999999) == 10
assert get_count_digits(-1000000000) == 10
assert get_count_digits(-999999999) == 9
assert get_count_digits(-100000000) == 9
assert get_count_digits(-99999999) == 8
assert get_count_digits(-10000000) == 8
assert get_count_digits(-9999999) == 7
assert get_count_digits(-1000000) == 7
assert get_count_digits(-999999) == 6
assert get_count_digits(-100000) == 6
assert get_count_digits(-99999) == 5
assert get_count_digits(-10000) == 5
assert get_count_digits(-9999) == 4
assert get_count_digits(-1000) == 4
assert get_count_digits(-999) == 3
assert get_count_digits(-100) == 3
assert get_count_digits(-99) == 2
assert get_count_digits(-10) == 2
assert get_count_digits(-9) == 1
assert get_count_digits(-1) == 1
assert get_count_digits(0) == 1
assert get_count_digits(1) == 1
assert get_count_digits(9) == 1
assert get_count_digits(10) == 2
assert get_count_digits(99) == 2
assert get_count_digits(100) == 3
assert get_count_digits(999) == 3
assert get_count_digits(1000) == 4
assert get_count_digits(9999) == 4
assert get_count_digits(10000) == 5
assert get_count_digits(99999) == 5
assert get_count_digits(100000) == 6
assert get_count_digits(999999) == 6
assert get_count_digits(1000000) == 7
assert get_count_digits(9999999) == 7
assert get_count_digits(10000000) == 8
assert get_count_digits(99999999) == 8
assert get_count_digits(100000000) == 9
assert get_count_digits(999999999) == 9
assert get_count_digits(1000000000) == 10
assert get_count_digits(9999999999) == 10
assert get_count_digits(10000000000) == 11
assert get_count_digits(99999999999) == 11
assert get_count_digits(100000000000) == 12
assert get_count_digits(999999999999) == 12
assert get_count_digits(1000000000000) == 13
assert get_count_digits(9999999999999) == 13
assert get_count_digits(10000000000000) == 14
assert get_count_digits(99999999999999) == 14
assert get_count_digits(100000000000000) == 15
assert get_count_digits(999999999999999) == 15
assert get_count_digits(1000000000000000) == 16
assert get_count_digits(9999999999999999) == 16
assert get_count_digits(10000000000000000) == 17
assert get_count_digits(99999999999999999) == 17
assert get_count_digits(100000000000000000) == 18
assert get_count_digits(999999999999999999) == 18
assert get_count_digits(1000000000000000000) == 19
assert get_count_digits(9999999999999999999) == 19
assert get_count_digits(10000000000000000000) == 20
assert get_count_digits(99999999999999999999) == 20

使用 Python 3.5 测试的所有代码示例


d
datanew

计算没有将整数转换为字符串的位数:

x=123
x=abs(x)
i = 0
while x >= 10**i:
    i +=1
# i is the number of digits

Nice 完全避免了字符串转换。
S
Stefan van den Akker

对于后人来说,毫无疑问是迄今为止解决这个问题最慢的方法:

def num_digits(num, number_of_calls=1):
    "Returns the number of digits of an integer num."
    if num == 0 or num == -1:
        return 1 if number_of_calls == 1 else 0
    else:
        return 1 + num_digits(num/10, number_of_calls+1)

C
Captain'Flam

这是一个庞大但快速的版本:

def nbdigit ( x ):
    if x >= 10000000000000000 : # 17 -
        return len( str( x ))
    if x < 100000000 : # 1 - 8
        if x < 10000 : # 1 - 4
            if x < 100             : return (x >= 10)+1 
            else                   : return (x >= 1000)+3
        else: # 5 - 8                                                 
            if x < 1000000         : return (x >= 100000)+5 
            else                   : return (x >= 10000000)+7
    else: # 9 - 16 
        if x < 1000000000000 : # 9 - 12
            if x < 10000000000     : return (x >= 1000000000)+9 
            else                   : return (x >= 100000000000)+11
        else: # 13 - 16
            if x < 100000000000000 : return (x >= 10000000000000)+13 
            else                   : return (x >= 1000000000000000)+15

对于不太大的数字,只有 5 次比较。在我的计算机上,它比 math.log10 版本快 30%,比 len( str()) 快 5%。好吧......如果你不疯狂地使用它,它就不那么有吸引力了。

这是我用来测试/测量我的功能的一组数字:

n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]

注意:它不管理负数,但适应很容易......


R
Robert William Hanks
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+1

b
batbrat

假设您要的是可以存储在整数中的最大数字,则该值取决于实现。我建议你在使用 python 时不要这样想。无论如何,相当大的值可以存储在python“整数”中。请记住,Python 使用鸭子类型!

编辑:我在澄清提问者想要位数之前给出了答案。为此,我同意接受的答案建议的方法。没有什么要补充的了!


佚名
def length(i):
  return len(str(i))

F
Frogboxe

可以使用以下方法快速完成整数:

len(str(abs(1234567890)))

得到绝对值“1234567890”的字符串长度

abs 返回没有任何负数的数字(只有数字的大小),str 将其转换/转换为字符串,len 返回该字符串的字符串长度。

如果您希望它适用于浮点数,您可以使用以下任一方法:

# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])

# Ignore just the decimal place
len(str(abs(0.1234567890)))-1

备查。


我认为截断输入数字本身(例如强制转换为 int)比截断其十进制字符串表示更简单:len(str(abs(int(0.1234567890)))) 返回 1。
不,那是行不通的。如果你把 0.17 变成一个整数,你会得到 0,它的长度将不同于 0.17 的长度
在第一种情况下,通过截断字符串表示中的所有内容(包括小数点),您可以有效地计算数字整数部分的长度,这也是我的建议。对于 0.17,两个解决方案都返回 1。
佚名

用科学记数法格式化并去掉指数:

int("{:.5e}".format(1000000).split("e")[1]) + 1

我不知道速度,但它很简单。

请注意小数点后的有效位数(“.5e”中的“5”如果将科学记数法的小数部分四舍五入到另一个数字,则可能会出现问题。我将其设置为任意大,但可以反映你知道的最大数的长度。


D
Del_sama
def count_digit(number):
  if number >= 10:
    count = 2
  else:
    count = 1
  while number//10 > 9:
    count += 1
    number = number//10
  return count

虽然此代码可能会解决问题,但including an explanation如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答以添加解释并说明适用的限制和假设。
v
vsminkov
def digits(n)
    count = 0
    if n == 0:
        return 1
    
    if n < 0:
        n *= -1

    while (n >= 10**count):
        count += 1
        n += n%10

    return count

print(digits(25))   # Should print 2
print(digits(144))  # Should print 3
print(digits(1000)) # Should print 4
print(digits(0))    # Should print 1

C
Chaitanya Kesanapalli

这是另一种计算任何数字小数点前位数的方法

from math import fabs

len(format(fabs(100),".0f"))
Out[102]: 3

len(format(fabs(1e10),".0f"))
Out[165]: 11

len(format(fabs(1235.4576),".0f"))
Out[166]: 4

我做了一个简短的基准测试,测试了 10,000 个循环

num     len(str(num))     ----  len(format(fabs(num),".0f")) ---- speed-up
2**1e0  2.179400e-07 sec  ----     8.577000e-07 sec          ---- 0.2541
2**1e1  2.396900e-07 sec  ----     8.668800e-07 sec          ---- 0.2765
2**1e2  9.587700e-07 sec  ----     1.330370e-06 sec          ---- 0.7207
2**1e3  2.321700e-06 sec  ----     1.761305e-05 sec          ---- 0.1318

它速度较慢,但更简单。

但即使是这个解决方案也确实给出了错误的结果 9999999999999998

len(format(fabs(9999999999999998),".0f"))
Out[146]: 16
len(format(fabs(9999999999999999),".0f"))
Out[145]: 17

P
Paul Roub

如果您必须要求用户提供输入,然后您必须计算有多少数字,那么您可以按照以下步骤操作:

count_number = input('Please enter a number\t')

print(len(count_number))

注意:永远不要将 int 作为用户输入。


您在此处描述的一个相当具体的情况,因为它实际上与字符串的长度有关。另外,我可以输入任何非数字字符,你仍然会相信它是一个数字。
D
Devvrat Chaubal

我的代码如下;我使用了 log10 方法:

from math import *

def digit_count(数字):

if number>1 and round(log10(number))>=log10(number) and number%10!=0 :
    return round(log10(number))
elif  number>1 and round(log10(number))<log10(number) and number%10!=0:
    return round(log10(number))+1
elif number%10==0 and number!=0:
    return int(log10(number)+1)
elif number==1 or number==0:
    return 1

我必须指定 1 和 0 的情况,因为 log10(1)=0 和 log10(0)=ND,因此不满足提到的条件。但是,此代码仅适用于整数。


c
cranberrysauce

最佳答案是说 mathlog10 更快,但我得到的结果表明 len(str(n)) 更快。

arr = []
for i in range(5000000):
    arr.append(random.randint(0,12345678901234567890))
%%timeit

for n in arr:
    len(str(n))
//2.72 s ± 304 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit

for n in arr:
    int(math.log10(n))+1
//3.13 s ± 545 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

此外,我没有在数学方法中添加逻辑来返回准确的结果,我只能想象它会更慢。

我不知道以前的答案如何证明数学方法更快。


K
Khaled
n = 3566002020360505
count = 0
while(n>0):
  count += 1
  n = n //10
print(f"The number of digits in the number are: {count}")

输出:数字中的位数为:16


s
san1512

如果您正在寻找不使用内置函数的解决方案。唯一需要注意的是您发送 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

类型提示 a: int 是正确的,这不适用于 float。例如,number_length(1.5) 返回 1
j
jodag

一种快速解决方案,它使用基于“Better way to compute floor of log(n,b) for integers n and b?”的 floor(log10(n)) 的自我更正实现。

import math

def floor_log(n, b):
    res = math.floor(math.log(n, b))
    c = b**res
    return res + (b*c <= n) - (c > n)

def num_digits(n):
    return 1 if n == 0 else 1 + floor_log(abs(n), 10)

这是相当快的,并且只要 n < 10**(2**52) (这真的很大)就可以工作。


D
Damn Ryder

这是最简单的方法,无需将 int 转换为字符串:

假设给出了一个 15 位的数字,例如; n=787878899999999;

n=787878899999999 
n=abs(n) // we are finding absolute value because if the number is negative int to string conversion will produce wrong output

count=0 //we have taken a counter variable which will increment itself till the last digit

while(n):
    n=n//10   /*Here we are removing the last digit of a number...it will remove until 0 digits will left...and we know that while(0) is False*/
    count+=1  /*this counter variable simply increase its value by 1 after deleting a digit from the original number
print(count)   /*when the while loop will become False because n=0, we will simply print the value of counter variable

输入 :

n=787878899999999

输出:

15

D
Discriminant

没有导入和函数的解决方案,如 str()

def numlen(num):
    result = 1
    divider = 10
    while num % divider != num:
        divider *= 10
        result += 1
    return result

a
alpc
coin_digit = str(coin_fark).split(".")[1]
coin_digit_len = len(coin_digit)
print(coin_digit_len)

此答案适用于浮点值(因为 .split(".")),而问题适用于整数。它假设输入数字已经是一个字符串。虽然得到 len(digits) 的解决方案已经回答 in the accepted answer
虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
g
ghostdog74
>>> a=12345
>>> a.__str__().__len__()
5

不要直接调用特殊方法。写成len(str(a))
@ghostdog74 仅仅因为有一个电源插座,并不意味着您必须将手指插入其中。
所以如果你这么反对它,你为什么不告诉我使用它有什么问题呢?
“魔术” __ 方法可供 Python 内部调用,而不是让您的代码直接调用。这是好莱坞框架模式:不要打电话给我们,我们会打电话给你。但是这个框架的意图是这些是标准 Python 内置函数可以使用的神奇方法,以便您的类可以自定义内置函数的行为。如果它是您的代码直接调用的方法,请给该方法一个非“__”的名称。这清楚地将那些旨在供程序员使用的方法与那些为 Python 内置回调提供的方法区分开来。
这是一个坏主意,因为已知宇宙中的其他所有人都使用 str() 和 len()。这是为了不同而不同,这本质上是一件坏事——更不用说它丑得要命。 -1。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅