Câu trả lời:
Nếu bạn muốn độ dài của một số nguyên như trong số chữ số trong số nguyên, bạn luôn có thể chuyển đổi nó thành chuỗi like str(133)
và tìm độ dài của nó như thế nào len(str(123))
.
Math.log10
phương pháp chỉ mất 7.486343383789062e-05 giây, nhanh hơn khoảng 1501388 lần!
Math.log10
thay thế.
Không chuyển đổi thành chuỗi
import math
digits = int(math.log10(n))+1
Để xử lý số 0 và số âm
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 '-'
Bạn có thể muốn đặt nó trong một chức năng :)
Dưới đây là một số điểm chuẩn. Các len(str())
đã được phía sau cho ngay cả con số khá nhỏ
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
cho 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 số tiền ) trả lại 72 không? Tôi nghĩ rằng tôi có thể dựa vào phương thức log10 nhưng tôi phải sử dụng len (str (x)) thay thế :(
math.log10(999999999999999)
bằng 14.999999999999998
để int(math.log10(999999999999999))
trở thành 14
. Nhưng sau đó math.log10(9999999999999999)
là bằng 16.0
. Có lẽ sử dụng round
là một giải pháp cho vấn đề này.
math.log10 nhanh nhưng gây ra sự cố khi số của bạn lớn hơn 999999999999997. Điều này là do số float có quá nhiều .9 giây, khiến kết quả bị làm tròn.
Giải pháp là sử dụng phương pháp bộ đếm while cho các số trên ngưỡng đó.
Để thực hiện việc này nhanh hơn nữa, hãy tạo 10 ^ 16, 10 ^ 17, v.v. và lưu trữ dưới dạng các biến trong danh sách. Bằng cách đó, nó giống như một bảng tra cứu.
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
. Thật thú vị khi thấy cách biểu diễn nhị phân lật các giá trị cho kết quả toán học không chính xác.
Python 2.*
int
lấy 4 hoặc 8 byte (32 hoặc 64 bit), tùy thuộc vào bản dựng Python của bạn. sys.maxint
( 2**31-1
đối với int 32 bit, 2**63-1
đối với int 64 bit) sẽ cho bạn biết khả năng nào trong hai khả năng có được.
Trong Python 3, int
s (như long
s trong Python 2) có thể có kích thước tùy ý lên đến lượng bộ nhớ khả dụng; sys.getsizeof
mang đến cho bạn một dấu hiệu tốt đối với bất kỳ giá trị nào đó, mặc dù nó không còn đếm số nguyên cần thiết cố định:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Nếu, như các câu trả lời khác cho thấy, bạn đang suy nghĩ về một số biểu diễn chuỗi của giá trị số nguyên, thì chỉ cần lấy len
biểu diễn đó, có thể là cơ sở 10 hoặc nếu không!
Đã vài năm kể từ khi câu hỏi này được hỏi, nhưng tôi đã biên soạn một điểm chuẩn của một số phương pháp để tính độ dài của một số nguyên.
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
(chức năng libc yêu cầu một số thiết lập mà tôi chưa bao gồm)
size_exp
là nhờ Brian Preslopsky, size_str
cảm ơn GeekTantra và size_math
cảm ơn John La Rooy
Đây là kết quả:
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)
(Tuyên bố từ chối trách nhiệm: chức năng được chạy trên đầu vào 1 đến 1.000.000)
Dưới đây là các kết quả cho sys.maxsize - 100000
đến 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)
Như bạn có thể thấy, mod_size
( len("%i" % i)
) là nhanh nhất, nhanh hơn một chút so với sử dụng str(i)
và nhanh hơn đáng kể so với những người khác.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(đoán đây là nó). Và nó không hoạt động đối với các số lớn hơn sys.maxsize
vì số dấu phẩy động không thể "rất lớn". Vì vậy, bất kỳ con số nào ở trên, tôi đoán bạn bị mắc kẹt với một trong những phương pháp chậm hơn.
Đặt số n
đó là số chữ số trong n
được cho bởi:
math.floor(math.log10(n))+1
Lưu ý rằng điều này sẽ đưa ra câu trả lời chính xác cho số nguyên + ve <10e15. Ngoài ra, giới hạn chính xác của loại math.log10
cú đá trả về và câu trả lời có thể bị tắt bởi 1. Tôi chỉ đơn giản là sử dụng len(str(n))
vượt quá điều đó; điều này đòi hỏi O(log(n))
thời gian tương tự như lặp lại với quyền hạn 10.
Cảm ơn @ SetiVolkylany đã đưa suy nghĩ của tôi đến giới hạn này. Thật đáng ngạc nhiên khi các giải pháp dường như đúng có sự cẩn thận trong các chi tiết thực hiện.
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
. Hãy xem câu trả lời của tôi stackoverflow.com/a/42736085/6003870 .
Đếm số chữ số w / o chuyển đổi số nguyên thành chuỗi:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
Như đã đề cập đến người dùng thân yêu @Calvintwr, chức năng math.log10
này có vấn đề ở một số ngoài phạm vi [-999999999999997, 999999999999997], trong đó chúng tôi gặp lỗi dấu phẩy động. Tôi gặp vấn đề này với JavaScript (Google V8 và NodeJS) và C (trình biên dịch GNU GCC), vì vậy 'purely mathematically'
không thể có giải pháp ở đây.
Dựa trên ý chính này và câu trả lời của người dùng thân yêu @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
Tôi đã thử nó trên các số có độ dài lên tới 20 (bao gồm) và tất cả đều đúng. Nó phải là đủ, bởi vì số nguyên tối đa dài trên hệ thống 64 bit là 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
Tất cả ví dụ về các mã được kiểm tra với Python 3.5
Đối với hậu thế, không còn nghi ngờ gì nữa, đây là giải pháp chậm nhất cho vấn đề này:
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
Giả sử bạn đang yêu cầu số lớn nhất bạn có thể lưu trữ trong một số nguyên, giá trị phụ thuộc vào việc triển khai. Tôi đề nghị bạn không nên nghĩ theo cách đó khi sử dụng python. Trong mọi trường hợp, một giá trị khá lớn có thể được lưu trữ trong một "số nguyên" của python. Hãy nhớ rằng, Python sử dụng gõ vịt!
Chỉnh sửa: Tôi đã đưa ra câu trả lời của mình trước khi làm rõ rằng người hỏi muốn số chữ số. Đối với điều đó, tôi đồng ý với phương pháp được đề xuất bởi câu trả lời được chấp nhận. Không có gì hơn để thêm!
def length(i):
return len(str(i))
Nó có thể được thực hiện cho các số nguyên một cách nhanh chóng bằng cách sử dụng:
len(str(abs(1234567890)))
Giá trị này có độ dài của chuỗi giá trị tuyệt đối là "1234567890"
abs
trả về số KHÔNG CÓ bất kỳ phủ định nào (chỉ độ lớn của số), str
ép / chuyển đổi nó thành một chuỗi và len
trả về độ dài chuỗi của chuỗi đó.
Nếu bạn muốn nó hoạt động cho phao, bạn có thể sử dụng một trong các cách sau:
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
Để tham khảo trong tương lai.
int
) so với cắt ngắn biểu diễn chuỗi thập phân của nó: len(str(abs(int(0.1234567890))))
trả về 1.
Định dạng trong ký hiệu khoa học và rút ra số mũ:
int("{:.5e}".format(1000000).split("e")[1]) + 1
Tôi không biết về tốc độ, nhưng nó đơn giản.
Vui lòng lưu ý số chữ số có nghĩa sau số thập phân ("5" trong ".5e" có thể là một vấn đề nếu nó làm tròn phần thập phân của ký hiệu khoa học sang chữ số khác. Tôi đặt nó lớn tùy ý, nhưng có thể phản ánh chiều dài của số lượng lớn nhất mà bạn biết.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
Nếu bạn phải yêu cầu người dùng cung cấp đầu vào và sau đó bạn phải đếm xem có bao nhiêu số thì bạn có thể làm theo điều này:
count_number = input('Please enter a number\t')
print(len(count_number))
Lưu ý: Không bao giờ lấy int làm đầu vào của người dùng.
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
Mã của tôi giống như sau, tôi đã sử dụng phương thức log10:
from math import *
def chữ số_count (số):
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
Tôi đã phải xác định trong trường hợp 1 và 0 vì log10 (1) = 0 và log10 (0) = ND và do đó điều kiện được đề cập không thỏa mãn. Tuy nhiên, mã này chỉ hoạt động cho toàn bộ số.
Đây là một phiên bản cồng kềnh nhưng nhanh chóng:
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
Chỉ có 5 so sánh cho số lượng không quá lớn. Trên máy tính của tôi, nó nhanh hơn khoảng 30% so với math.log10
phiên bản và nhanh hơn 5% so với phiên bản len( str())
. Ok ... không hấp dẫn lắm nếu bạn không sử dụng nó một cách giận dữ.
Và đây là tập hợp các số tôi đã sử dụng để kiểm tra / đo chức năng của mình:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
NB: nó không quản lý số âm, nhưng việc điều chỉnh rất dễ dàng ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.