파이썬에서 정수의 길이


232

파이썬에서 정수의 자릿수를 어떻게 찾습니까?


1
귀하의 질문을 이해하지 못합니다. 정수의 크기를 의미 했습니까? 자릿수를 찾으시겠습니까? 명확히하십시오.
batbrat

답변:


317

정수의 자릿수와 같이 정수의 길이를 원하면 항상 문자열처럼 변환 str(133)하고 길이를 찾을 수 len(str(123))있습니다.


18
물론 자릿수를 찾으려면 음수 부호를 계산하므로 음수에 비해 너무 큰 결과가 생성됩니다.
Chris Upchurch

37
이봐, 이것은 느린 해결책이다. 나는 임의의 6 자리 숫자를 계승하여 길이를 찾았습니다. 이 방법은 95.891 초가 걸렸 습니다 . 그리고 Math.log10방법은했다 7.486343383789062e-05 약 초 1,501,388 빠른 시간!
FadedCoder

1
이것은 느리지 않지만 많은 메모리를 소비하며 많은 수의 문제를 일으킬 수 있습니다. 사용하는 Math.log10대신.
Peyman

245

문자열로 변환하지 않고

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

5
이를 위해 log10을 사용하는 것은 수학자의 솔루션입니다. len (str ()) 사용은 프로그래머의 솔루션이며 더 명확하고 간단합니다.
Glenn Maynard

68
@ Glenn : 분명히 이것이 나쁜 해결 책임을 암시하지 않기를 바랍니다. 프로그래머의 순진한 O (log10 n) 솔루션은 임시 프로토 타입 코드에서 잘 작동하지만 프로덕션 코드 또는 공용 API에서 수학자에게 우아한 O (1) 솔루션을 보는 것이 좋습니다. gnibbler의 경우 +1
Juliet

5
@gnibbler : +1 log10을 사용하여 숫자의 크기를 찾을 수 있다는 것을 결코 알지 못했습니다. 한 번만 더 투표 할 수 있기를 바랍니다 :).
Abbas

14
안녕하세요! 나는 뭔가 이상한, 왜 저를 설명해주십시오 당신의 캔 누구나 이동 int(math.log10(x)) +1을 위해 99999999999999999999999999999999999999999999999999999999999999999999999( 71 나인 반환) (72) ? 나는 log10 방법에 의존 할 수 있다고 생각했지만 대신 len (str (x))을 사용해야합니다. (
Marecky

6
나는 이상한 행동의 이유를 알고 있다고 생각합니다. 예를 들어 부동 소수점 부정확성 때문입니다. math.log10(999999999999999)같은지 14.999999999999998그렇게 int(math.log10(999999999999999))된다 14. 그러나 다음 math.log10(9999999999999999)과 같습니다 16.0. 어쩌면 사용 round하는 것이이 문제에 대한 해결책 일 것입니다.
jamylak

43

모든 math.log10 솔루션은 문제를 제공합니다.

math.log10은 빠르지 만 숫자가 999999999999997보다 큰 경우 문제가 발생합니다. 이는 float에 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. 이진 표현이 값을 뒤집어 수학적으로 잘못된 결과를 얻는 방법을 보는 것은 흥미 롭습니다.
WloHu

그렇다면 len (str (num)) 더 낫습니다
Vighnesh Raut

2
@Vighnesh Raut : 그리고 속도가 느려짐
Chaitanya Bangera

"정확한 결과를 제공하는 부동 소수점 연산에 의존하는 것은 위험합니다."-핵심 Python 개발 팀의 구성원 인 Mark Dickinson bugs.python.org/issue3724
Sreeragh AR

26

Python 2.* int은 Python 빌드에 따라 4 또는 8 바이트 (32 또는 64 비트)를 사용합니다. sys.maxint( 2**31-132 비트 정수의 2**63-1경우 64 비트 정수의 경우)는 두 가지 가능성 중 어느 것을 얻을 수 있는지 알려줍니다.

Python 3에서 ints ( longPython 2의 s 와 같은 )는 사용 가능한 메모리 양까지 임의의 크기를 사용할 수 있습니다. sys.getsizeof그것은 비록 당신에게 주어진 가치에 대해 좋은 표시를 제공 않습니다 일부 고정 오버 헤드 수 :

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

다른 답변에서 알 수 있듯이 정수 값의 문자열 표현에 대해 생각하고 len있다면 그 표현을 기본 10 또는 다른 식으로 가져 가십시오 !


이 답변에 마이너스가 적용되었습니다. 그것은 정보를 제공하고 문제의 그럴듯한 점에 관한 것입니다 ( 'len'이 원하는 것이 더 구체적이라면). +1
mjv

이것은 흥미로워 보이지만 길이를 추출하는 방법을 잘 모르겠습니다
Tjorriemorrie

17

이 질문을 한 지 몇 년이 지났지 만 정수 길이를 계산하기 위해 여러 가지 방법의 벤치 마크를 작성했습니다.

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_expBrian Preslopsky, size_strGeekTantra, size_mathJohn 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으로는 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)다른 것보다 훨씬 빠릅니다.


실제로 libc 설정을 포함시켜야합니다 libc = ctyle.CDLL('libc.so.6', use_errno=True)(이것이 추측입니다). sys.maxsize부동 소수점 숫자는 "매우 클 수"없기 때문에 보다 큰 숫자에서는 작동하지 않습니다 . 그래서 그 이상의 숫자는 느린 방법 중 하나에 갇힌 것 같습니다.
Torxed

15

수가하자 n자릿수 다음 수 n에 의해 주어진다 :

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

이것은 + ve 정수 <10e15에 대한 정답을 제공합니다. 리턴 타입의 math.log10킥과 그 대답 의 정밀도 한계는 1만큼 떨어질 수 있습니다 len(str(n)). 이를 위해서는 O(log(n))10의 거듭 제곱을 반복하는 것과 동일한 시간 이 필요합니다 .

이 한계에 관심을 가져 주신 @SetiVolkylany에게 감사드립니다. 겉보기에 올바른 솔루션이 구현 세부 사항에 얼마나 심각한 지 놀랍습니다.


1
n이 [-999999999999997, 999999999999997] 범위를 벗어난 경우 작동하지 않습니다.
PADYMKO

@ 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))].
BiGYaN

2
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을보십시오 .
PADYMKO

12

글쎄, 문자열로 변환하지 않고 나는 다음과 같은 일을 할 것이다.

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

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

미니멀리스트 재귀 FTW


1
많은 수의 재귀 한계에 도달합니다.
nog642

9

정수를 문자열로 변환하지 않고 자릿수를 계산하십시오.

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

좋은 것은 문자열 변환을 완전히 피합니다.
Patrick Mutuku

7

친애하는 사용자 @Calvintwr이 언급했듯이 함수 math.log10는 [-999999999999997, 999999999999997] 범위를 벗어난 숫자에 문제가 있으며 여기서 부동 소수점 오류가 발생합니다. JavaScript (Google V8 및 NodeJS) 및 C (GNU GCC 컴파일러) 에서이 문제가 있었으므로 'purely mathematically'여기서는 해결책이 불가능합니다.


요점대답을 바탕으로 친애하는 사용자 @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로 테스트 한 모든 코드 예제


3

후손의 경우,이 문제에 대한 가장 느린 해결책은 의심 할 여지가 없습니다.

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)


1

정수에 저장할 수있는 가장 큰 숫자를 요구한다고 가정하면 값은 구현에 따라 다릅니다. 파이썬을 사용할 때 그렇게 생각하지 않는 것이 좋습니다. 어쨌든 파이썬 '정수'에 상당히 큰 값을 저장할 수 있습니다. 파이썬은 오리 타이핑을 사용한다는 것을 기억하십시오!

편집 : 나는 asker가 자릿수를 원한다는 것을 명확히하기 전에 대답했다. 이를 위해, 나는 수용 된 대답에서 제안한 방법에 동의합니다. 더 이상 추가 할 것이 없습니다!


1
def length(i):
  return len(str(i))

1

다음을 사용하여 정수에 대해 빠르게 수행 할 수 있습니다.

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.17의 경우 두 솔루션 모두 1을 반환합니다.
David Foerster

0

과학적 표기법으로 형식화하고 지수를 빼냅니다.

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

속도에 대해서는 잘 모르지만 간단합니다.

소수점 이하의 유효 자릿수 ( ".5e"의 "5"는 과학 표기법의 소수점 이하 자릿수를 다른 숫자로 반올림하면 문제가 될 수 있음)에 유의하십시오. 임의로 설정했지만 당신이 아는 가장 큰 숫자의 길이.


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

이 코드가 문제를 해결하는 방법과 이유에 대한 설명포함 하여 질문을 해결할 수는 있지만 게시물의 품질을 향상시키는 데 도움이되고 더 많은 투표를 할 수 있습니다. 지금 질문하는 사람이 아니라 독자들에게 질문에 대답하고 있음을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Adrian Mole

0

사용자에게 입력을 요청하고 숫자가 몇 개인 지 계산해야하는 경우 다음을 수행 할 수 있습니다.

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

print(len(count_number))

참고 : 사용자 입력으로 int를 사용하지 마십시오.


실제로는 문자열의 길이와 관련이 있기 때문에 여기서는 다소 구체적인 경우를 설명합니다. 또한 숫자가 아닌 문자를 입력 할 수 있으며 여전히 숫자라고 생각할 것입니다.

0
def digits(n)
    count = 0
    if n == 0:
        return 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

0

내 코드는 다음과 같습니다 .log10 방법을 사용했습니다.

from math import *

데프 자리수 (숫자) :

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

log10 (1) = 0 및 log10 (0) = ND이므로 1과 0의 경우 지정해야하므로 언급 된 조건이 충족되지 않습니다. 그러나이 코드는 정수에만 적용됩니다.


0

다음은 부피가 크지 만 빠른 버전입니다.

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 % 빠르며 다른 것보다 5 % 빠릅니다 len( str()). 좋아 ... 분노하게 사용하지 않으면 매력적이지 않습니다.

그리고 여기 내 기능을 테스트 / 측정하는 데 사용 된 숫자 세트가 있습니다.

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

NB : 음수를 관리하지 않지만 적응은 쉽습니다 ...


-13
>>> a=12345
>>> a.__str__().__len__()
5

6
특별한 메소드를 직접 호출하지 마십시오. 그게 기록되었습니다 len(str(a)).
Mike Graham

8
@ ghostdog74 전기 소켓이 있다고해서 손가락을 집어 넣어야하는 것은 아닙니다.

3
당신이 그것에 대해 반대한다면, 왜 그것을 사용하는 것에 문제가 있는지 말하지 않습니까?
ghostdog74

11
"매직"__ 메소드는 코드가 직접 호출하는 것이 아니라 파이썬 내부가 호출 할 수있는 방법입니다. 할리우드 프레임 워크 패턴입니다. 전화하지 마십시오. 전화하겠습니다. 그러나이 프레임 워크의 목적은 표준 Python 내장 기능을 사용하는 마법의 메소드이므로 클래스가 내장 기능을 사용자 정의 할 수 있습니다. 코드가 직접 호출하는 방법 인 경우 메소드에 "" "이외의 이름을 지정하십시오. 이것은 프로그래머가 소비하는 메소드와 파이썬 내장 콜백을 제공하는 메소드를 명확하게 분리합니다.
PaulMcG

7
알려진 우주의 다른 모든 사람들이 str ()과 len ()을 사용 하기 때문에 나쁜 생각 입니다. 이것은 다른 것 때문에 다르다. 본질적으로 나쁜 것입니다. 그것은 단지 못 생겼다는 것은 말할 것도 없습니다. -1.
Glenn Maynard 님
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.