답변:
정수의 자릿수와 같이 정수의 길이를 원하면 항상 문자열처럼 변환 str(133)
하고 길이를 찾을 수 len(str(123))
있습니다.
Math.log10
방법은했다 만 7.486343383789062e-05 약 초 1,501,388 빠른 시간!
Math.log10
대신.
문자열로 변환하지 않고
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
int(math.log10(x)) +1
을 위해 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 나인 반환) (72) ? 나는 log10 방법에 의존 할 수 있다고 생각했지만 대신 len (str (x))을 사용해야합니다. (
math.log10(999999999999999)
같은지 14.999999999999998
그렇게 int(math.log10(999999999999999))
된다 14
. 그러나 다음 math.log10(9999999999999999)
과 같습니다 16.0
. 어쩌면 사용 round
하는 것이이 문제에 대한 해결책 일 것입니다.
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
. 이진 표현이 값을 뒤집어 수학적으로 잘못된 결과를 얻는 방법을 보는 것은 흥미 롭습니다.
Python 2.*
int
은 Python 빌드에 따라 4 또는 8 바이트 (32 또는 64 비트)를 사용합니다. sys.maxint
( 2**31-1
32 비트 정수의 2**63-1
경우 64 비트 정수의 경우)는 두 가지 가능성 중 어느 것을 얻을 수 있는지 알려줍니다.
Python 3에서 int
s ( long
Python 2의 s 와 같은 )는 사용 가능한 메모리 양까지 임의의 크기를 사용할 수 있습니다. sys.getsizeof
그것은 비록 당신에게 주어진 가치에 대해 좋은 표시를 제공 않습니다 일부 고정 오버 헤드 수 :
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
다른 답변에서 알 수 있듯이 정수 값의 문자열 표현에 대해 생각하고 len
있다면 그 표현을 기본 10 또는 다른 식으로 가져 가십시오 !
이 질문을 한 지 몇 년이 지났지 만 정수 길이를 계산하기 위해 여러 가지 방법의 벤치 마크를 작성했습니다.
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
으로는 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 = ctyle.CDLL('libc.so.6', use_errno=True)
(이것이 추측입니다). sys.maxsize
부동 소수점 숫자는 "매우 클 수"없기 때문에 보다 큰 숫자에서는 작동하지 않습니다 . 그래서 그 이상의 숫자는 느린 방법 중 하나에 갇힌 것 같습니다.
수가하자 n
자릿수 다음 수 n
에 의해 주어진다 :
math.floor(math.log10(n))+1
이것은 + ve 정수 <10e15에 대한 정답을 제공합니다. 리턴 타입의 math.log10
킥과 그 대답 의 정밀도 한계는 1만큼 떨어질 수 있습니다 len(str(n))
. 이를 위해서는 O(log(n))
10의 거듭 제곱을 반복하는 것과 동일한 시간 이 필요합니다 .
이 한계에 관심을 가져 주신 @SetiVolkylany에게 감사드립니다. 겉보기에 올바른 솔루션이 구현 세부 사항에 얼마나 심각한 지 놀랍습니다.
assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))]
.
>>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0
. 내 답변 stackoverflow.com/a/42736085/6003870을보십시오 .
정수를 문자열로 변환하지 않고 자릿수를 계산하십시오.
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
친애하는 사용자 @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로 테스트 한 모든 코드 예제
후손의 경우,이 문제에 대한 가장 느린 해결책은 의심 할 여지가 없습니다.
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)
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+1
def length(i):
return len(str(i))
다음을 사용하여 정수에 대해 빠르게 수행 할 수 있습니다.
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
과학적 표기법으로 형식화하고 지수를 빼냅니다.
int("{:.5e}".format(1000000).split("e")[1]) + 1
속도에 대해서는 잘 모르지만 간단합니다.
소수점 이하의 유효 자릿수 ( ".5e"의 "5"는 과학 표기법의 소수점 이하 자릿수를 다른 숫자로 반올림하면 문제가 될 수 있음)에 유의하십시오. 임의로 설정했지만 당신이 아는 가장 큰 숫자의 길이.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
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
내 코드는 다음과 같습니다 .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의 경우 지정해야하므로 언급 된 조건이 충족되지 않습니다. 그러나이 코드는 정수에만 적용됩니다.
다음은 부피가 크지 만 빠른 버전입니다.
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 : 음수를 관리하지 않지만 적응은 쉽습니다 ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.