ใน Python คุณจะหาจำนวนหลักในจำนวนเต็มได้อย่างไร
ใน Python คุณจะหาจำนวนหลักในจำนวนเต็มได้อย่างไร
คำตอบ:
หากคุณต้องการความยาวของจำนวนเต็มเช่นเดียวกับจำนวนหลักในจำนวนเต็มคุณสามารถแปลงให้เป็นสตริงเหมือนstr(133)
และค้นหาความยาวlen(str(123))
ได้
Math.log10
วิธีการใช้เวลาเพียง 7.486343383789062e-05วินาทีเร็วขึ้นประมาณ1501388เท่า!
Math.log10
แทน
โดยไม่ต้องแปลงเป็นสตริง
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
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 เพราะการลอยมีจำนวนมากเกินไป. 9s ทำให้เกิดผลลัพธ์ที่จะปัดเศษขึ้น
การแก้ปัญหาคือการใช้วิธีการนับขณะสำหรับตัวเลขที่สูงกว่าเกณฑ์
หากต้องการทำให้เร็วยิ่งขึ้นให้สร้าง 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
s ใช้เวลา 4 หรือ 8 ไบต์ (32 หรือ 64 บิต) ขึ้นอยู่กับการสร้าง Python ของคุณ sys.maxint
( 2**31-1
สำหรับ 32- บิต int, 2**63-1
64- บิต ints) จะบอกคุณว่ามีสองวิธีที่จะได้รับ
ใน Python 3, int
s (เหมือนกับlong
s ใน Python 2) สามารถเพิ่มขนาดได้ตามจำนวนหน่วยความจำที่มีอยู่โดยพลการ 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
Python3.5 ดูคำตอบของฉันstackoverflow.com/a/42736085/6003870
ดีโดยไม่ต้องแปลงเป็นสตริงฉันจะทำสิ่งที่ชอบ:
def lenDigits(x):
"""
Assumes int(x)
"""
x = abs(x)
if x < 10:
return 1
return 1 + lenDigits(x / 10)
การเรียกซ้ำ FTW ที่เรียบง่าย
นับจำนวนหลักที่ไม่มีการแปลงจำนวนเต็มเป็นสตริง:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
ดังที่ได้กล่าวถึงผู้ใช้ที่รัก @Calvintwr ฟังก์ชั่นmath.log10
มีปัญหาในจำนวนนอกช่วง [-99999999999999997, 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
สมมติว่าคุณขอหมายเลขที่ใหญ่ที่สุดที่คุณสามารถเก็บไว้ในจำนวนเต็มค่าขึ้นอยู่กับการใช้งาน ฉันขอแนะนำให้คุณไม่คิดอย่างนั้นเมื่อใช้ python ไม่ว่าในกรณีใดค่ามากจะถูกเก็บไว้ในไพ ธ อน 'จำนวนเต็ม' จำไว้ว่า Python ใช้การพิมพ์เป็ด!
แก้ไข: ฉันได้รับคำตอบก่อนที่จะชี้แจงว่าผู้ถามต้องการจำนวนหลัก เพื่อที่ฉันเห็นด้วยกับวิธีการที่แนะนำโดยคำตอบที่ได้รับการยอมรับ ไม่มีอะไรเพิ่มเติมที่จะเพิ่ม!
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
ฉันไม่รู้เกี่ยวกับความเร็ว แต่มันง่าย
โปรดทราบจำนวนหลักที่สำคัญหลังจุดทศนิยม ("5" ใน ".5e" อาจเป็นปัญหาได้หากมันปัดเศษทศนิยมของเครื่องหมายทางวิทยาศาสตร์เป็นตัวเลขอื่นให้เป็นตัวเลขอื่นฉันตั้งค่ามันใหญ่โดยพล แต่อาจสะท้อน ความยาวของจำนวนมากที่สุดที่คุณรู้
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
หากคุณต้องขอให้ผู้ใช้ป้อนข้อมูลจากนั้นคุณต้องนับจำนวนตัวเลขที่มีคุณสามารถทำตามนี้:
count_number = input('Please enter a number\t')
print(len(count_number))
หมายเหตุ: ไม่ต้องใช้ int เป็นอินพุตของผู้ใช้
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 *
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 และด้วยเหตุนี้เงื่อนไขดังกล่าวจึงไม่เป็นที่พอใจ อย่างไรก็ตามรหัสนี้ใช้ได้กับทั้งจำนวนเท่านั้น
นี่คือรุ่นที่ใหญ่ แต่เร็ว:
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 รายการที่มีตัวเลขไม่ใหญ่เกินไป บนคอมพิวเตอร์ของฉันมันเป็นประมาณ 30% เร็วกว่าmath.log10
รุ่นและ 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))
ที่เขียน