Відповіді:
Якщо ви хочете, щоб довжина цілого числа була як у кількості цифр у цілому, ви завжди можете перетворити її у рядок типу 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-бітових ints, 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
це завдяки Брайану Преслопському, size_str
завдяки GeekTantra і size_math
завдяки Джону Ла Роу
Ось результати:
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
Якщо припустити, що ви запитуєте про найбільшу кількість, яку ви можете зберігати в ціле число, значення залежить від реалізації. Я пропоную вам не думати таким чином під час використання 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 *
визначити_кілька (кількість):
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))
.