ความยาวของเลขจำนวนเต็มใน Python


232

ใน Python คุณจะหาจำนวนหลักในจำนวนเต็มได้อย่างไร


1
ฉันไม่เข้าใจคำถามของคุณ คุณหมายถึงขนาดของจำนวนเต็มหรือไม่ คุณต้องการค้นหาจำนวนหลักหรือไม่? กรุณาชี้แจง
batbrat

คำตอบ:


317

หากคุณต้องการความยาวของจำนวนเต็มเช่นเดียวกับจำนวนหลักในจำนวนเต็มคุณสามารถแปลงให้เป็นสตริงเหมือนstr(133)และค้นหาความยาวlen(str(123))ได้


18
แน่นอนหากคุณกำลังมองหาจำนวนหลักสิ่งนี้จะสร้างผลลัพธ์ที่ใหญ่เกินไปสำหรับจำนวนลบเนื่องจากจะนับเครื่องหมายลบ
Chris Upchurch

37
เฮ้นี่เป็นทางออกที่ช้า ฉันทำแฟกทอเรียลด้วยตัวเลขสุ่ม 6 หลักและพบความยาว วิธีนี้ใช้เวลา95.891วินาที และMath.log10วิธีการใช้เวลาเพียง 7.486343383789062e-05วินาทีเร็วขึ้นประมาณ1501388เท่า!
FadedCoder

1
นี่ไม่ใช่แค่ช้า แต่ใช้หน่วยความจำมากขึ้นและอาจทำให้เกิดปัญหาในจำนวนมาก ใช้Math.log10แทน
Peyman

245

โดยไม่ต้องแปลงเป็นสตริง

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

5
การใช้ log10 สำหรับสิ่งนี้คือคำตอบของนักคณิตศาสตร์ using len (str ()) เป็นวิธีแก้ปัญหาของโปรแกรมเมอร์และชัดเจนและง่ายขึ้น
Glenn Maynard

68
@ เกล็น: ฉันหวังว่าคุณคงไม่ได้หมายความว่านี่เป็นทางออกที่ไม่ดี โซลูชันไร้เดียงสา O (log10 n) ของโปรแกรมเมอร์ทำงานได้ดีใน ad-hoc, รหัสต้นแบบ - แต่ฉันค่อนข้างจะเห็นนักคณิตศาสตร์ O (1) โซลูชันที่สง่างามในรหัสการผลิตหรือ API สาธารณะ +1 สำหรับ gnibbler
Juliet

5
@gnibbler: +1 ไม่เคยรู้เลยว่า log10 สามารถใช้หาขนาดของตัวเลขได้ หวังว่าฉันจะได้คะแนนมากขึ้นอีกครั้ง :)
Abbas

14
Hi! ฉันไปสิ่งที่แปลกทุกคนสามารถของคุณโปรดอธิบายว่าทำไม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 เพราะการลอยมีจำนวนมากเกินไป. 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นั่นคือการที่ดีเคาน์เตอร์ตัวอย่างสำหรับ เป็นที่น่าสนใจที่จะเห็นว่าการเป็นตัวแทนไบนารีพลิกค่าที่ให้ผลลัพธ์ที่ไม่ถูกต้องทางคณิตศาสตร์
WloHu

จากนั้น len (str (num)) จะดีกว่า
Vighnesh Raut

2
@Vighnesh Raut: และขนาดช้าลง
Chaitanya Bangera

"มันเป็นสิ่งที่อันตรายที่จะพึ่งพาการดำเนินงานจุดลอยให้ผลลัพธ์ที่แน่นอน" - มาร์คดิกคินสันเป็นสมาชิกของแกนหลามทีมพัฒนา bugs.python.org/issue3724
Sreeragh AR

26

Python 2.* ints ใช้เวลา 4 หรือ 8 ไบต์ (32 หรือ 64 บิต) ขึ้นอยู่กับการสร้าง Python ของคุณ sys.maxint( 2**31-1สำหรับ 32- บิต int, 2**63-164- บิต ints) จะบอกคุณว่ามีสองวิธีที่จะได้รับ

ใน Python 3, ints (เหมือนกับlongs ใน Python 2) สามารถเพิ่มขนาดได้ตามจำนวนหน่วยความจำที่มีอยู่โดยพลการ 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_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 ไว้ด้วย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 ฉันทดสอบจนถึง 50 หลักสำหรับ python2.7 และ 3.5 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 หรือ >>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0Python3.5 ดูคำตอบของฉัน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

Nice หนึ่งหลีกเลี่ยงการแปลงสตริงอย่างสมบูรณ์
Patrick Mutuku

7

ดังที่ได้กล่าวถึงผู้ใช้ที่รัก @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


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

สมมติว่าคุณขอหมายเลขที่ใหญ่ที่สุดที่คุณสามารถเก็บไว้ในจำนวนเต็มค่าขึ้นอยู่กับการใช้งาน ฉันขอแนะนำให้คุณไม่คิดอย่างนั้นเมื่อใช้ python ไม่ว่าในกรณีใดค่ามากจะถูกเก็บไว้ในไพ ธ อน 'จำนวนเต็ม' จำไว้ว่า Python ใช้การพิมพ์เป็ด!

แก้ไข: ฉันได้รับคำตอบก่อนที่จะชี้แจงว่าผู้ถามต้องการจำนวนหลัก เพื่อที่ฉันเห็นด้วยกับวิธีการที่แนะนำโดยคำตอบที่ได้รับการยอมรับ ไม่มีอะไรเพิ่มเติมที่จะเพิ่ม!


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
David Foerster

ไม่นั่นไม่ได้ผล หากคุณเปลี่ยน 0.17 เป็นจำนวนเต็มคุณจะได้รับ 0 และความยาวของมันจะแตกต่างจากความยาว 0.17
Frogboxe

ในกรณีแรกโดยการตัดทุกอย่างจากและรวมถึงจุดทศนิยมจากการแทนสตริงคุณจะคำนวณความยาวของส่วนที่สำคัญของตัวเลขได้อย่างมีประสิทธิภาพซึ่งเป็นสิ่งที่ฉันแนะนำเช่นกัน สำหรับ 0.17 ทั้งสองวิธีคืนค่า 1
David Foerster

0

จัดรูปแบบในสัญลักษณ์ทางวิทยาศาสตร์และดึงเลขชี้กำลัง:

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

ฉันไม่รู้เกี่ยวกับความเร็ว แต่มันง่าย

โปรดทราบจำนวนหลักที่สำคัญหลังจุดทศนิยม ("5" ใน ".5e" อาจเป็นปัญหาได้หากมันปัดเศษทศนิยมของเครื่องหมายทางวิทยาศาสตร์เป็นตัวเลขอื่นให้เป็นตัวเลขอื่นฉันตั้งค่ามันใหญ่โดยพล แต่อาจสะท้อน ความยาวของจำนวนมากที่สุดที่คุณรู้


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 *

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 และด้วยเหตุนี้เงื่อนไขดังกล่าวจึงไม่เป็นที่พอใจ อย่างไรก็ตามรหัสนี้ใช้ได้กับทั้งจำนวนเท่านั้น


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 รายการที่มีตัวเลขไม่ใหญ่เกินไป บนคอมพิวเตอร์ของฉันมันเป็นประมาณ 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: มันไม่ได้จัดการตัวเลขลบ แต่การปรับตัวนั้นง่าย ...


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

6
อย่าเรียกวิธีพิเศษโดยตรง len(str(a))ที่เขียน
Mike Graham

8
@ ghostdog74 เพียงเพราะมีปลั๊กไฟไม่ได้หมายความว่าคุณต้องใช้นิ้วของคุณ

3
ดังนั้นถ้าคุณต่อต้านมันทำไมคุณไม่บอกฉันว่ามีอะไรผิดปกติกับการใช้มัน?
ghostdog74

11
"Magic" __ method มีไว้สำหรับ Python เพื่อโทรกลับภายในไม่ใช่สำหรับรหัสของคุณที่จะโทรโดยตรง เป็นรูปแบบ Hollywood Framework: อย่าโทรหาเราเราจะโทรหาคุณ แต่จุดประสงค์ของกรอบการทำงานนี้คือสิ่งเหล่านี้เป็นวิธีการมหัศจรรย์สำหรับตัวสร้าง Python มาตรฐานที่จะใช้งานเพื่อให้ชั้นเรียนของคุณสามารถปรับแต่งพฤติกรรมของบิวด์อินได้ หากเป็นวิธีสำหรับรหัสของคุณโทรโดยตรงให้ตั้งชื่อที่ไม่ใช่ "__" วิธีนี้แยกวิธีการที่มีไว้สำหรับการใช้โปรแกรมเมอร์อย่างชัดเจนกับวิธีที่มีไว้สำหรับการโทรกลับจาก Python ในตัว
PaulMcG

7
เป็นความคิดที่ไม่ดีเพราะทุกคนในจักรวาลที่รู้จักกันใช้ str () และ len () นี่คือสิ่งที่แตกต่างกันเพื่อความแตกต่างซึ่งเป็นสิ่งที่เลวร้ายโดยเนื้อแท้ - ไม่พูดถึงว่ามันน่าเกลียดเหมือนนรก -1
Glenn Maynard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.