Я не понимаю твой вопрос. Вы имели в виду размер целого числа? Хотите узнать количество цифр? Просьба уточнить.
Batbrat
Ответы:
317
Если вы хотите, чтобы длина целого числа была равна числу цифр в целом числе, вы всегда можете преобразовать его в строку типа like str(133)и найти ее длину like len(str(123)).
Конечно, если вы ищете количество цифр, это даст слишком большой результат для отрицательных чисел, поскольку он будет считать отрицательный знак.
Крис Апчерч
37
Эй, это медленное решение. Я сделал факториал случайного 6-значного числа и нашел его длину. Этот метод занял 95,891 секунды. И Math.log10метод занял всего 7,486343383789062e-05 секунд, примерно в 1501388 раз быстрее!
FadedCoder
1
Это не просто медленно, но потребляет гораздо больше памяти и может вызвать проблемы в больших количествах. используйте Math.log10вместо этого.
Пейман
246
Без преобразования в строку
import math
digits = int(math.log10(n))+1
Также обрабатывать ноль и отрицательные числа
import math
if n >0:
digits = int(math.log10(n))+1elif n ==0:
digits =1else:
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
Использование log10 для этого является решением математика; Использование len (str ()) - решение для программиста, и оно становится понятнее и проще.
Гленн Мейнард
68
@ Гленн: Я, конечно, надеюсь, что вы не намекаете, что это плохое решение. Наивное решение O (log10 n) для программиста хорошо работает в специальном прототипном коде, но я бы предпочел, чтобы математики изящно использовали решение O (1) в производственном коде или публичном API. +1 за гнибблера.
Джульетта
5
@gnibbler: +1. Никогда не осознавал, что log10 можно использовать для определения величины числа. Жаль, что я не мог голосовать больше одного раза :).
Аббас
14
Здравствуй! Я иду что-то странное, может кто-нибудь из вас, пожалуйста, объясните мне, почему 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. Это потому, что у float слишком много .9s, в результате чего результат округляется.
Решение состоит в том, чтобы использовать метод счетчика while для чисел выше этого порога.
Чтобы сделать это еще быстрее, создайте 10 ^ 16, 10 ^ 17 и так далее и сохраните в виде переменных в списке. Таким образом, это похоже на поиск по таблице.
Спасибо. Это хороший контрпример math.log10. Интересно посмотреть, как двоичное представление переворачивает значения, давая математически неверный результат.
WloHu
тогда len (str (num)) будет лучше
Vighnesh Raut
2
@Vighnesh Raut: И величины медленнее
Чайтанья Бангера
«Опасно полагаться на операции с плавающей запятой, дающие точные результаты», - Марк Дикинсон, член основной команды разработчиков Python bugs.python.org/issue3724
Sreeragh AR
26
Python 2.*intзанимает 4 или 8 байтов (32 или 64 бита), в зависимости от вашей сборки Python. sys.maxint( 2**31-1для 32-битных целых, 2**63-1для 64-битных целых) скажет вам, какая из двух возможностей имеет место.
В Python 3 ints (как longs в Python 2) может принимать произвольные размеры вплоть до объема доступной памяти; sys.getsizeofдает индикацию хорошо для любого заданного значения, хотя это также рассчитывать некоторые фиксированные накладные расходы:
Если, как показывают другие ответы, вы думаете о некотором строковом представлении целочисленного значения, то просто возьмите lenэто представление, будь то в базе 10 или иначе!
Извините, этот ответ получил минус-ред. Он информативен и правдоподобен в вопросе (если бы он был только более конкретным в отношении того, какой «лен» желателен). +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 stringdef math_size(i):return1+ math.floor(math.log10(i))# 1 + floor of log10 of idef exp_size(i):return int("{:.5e}".format(i).split("e")[1])+1# e.g. `1e10` -> `10` + 1 -> 11def 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Джону Ла Руи
Вот результаты:
Timefor libc size:1.2204μs
Timefor string size:309.41 ns
Timefor math size:329.54 ns
Timefor exp size:1.4902μs
Timefor mod size:249.36 ns
Timefor 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:
Timefor libc size:1.4686μs
Timefor string size:395.76 ns
Timefor math size:485.94 ns
Timefor exp size:1.6826μs
Timefor mod size:364.25 ns
Timefor 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 за мое внимание к этому ограничению. Удивительно, как казалось бы правильные решения имеют недостатки в деталях реализации.
Это не работает, если 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 или Python3.5 >>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0. Посмотри мой ответ stackoverflow.com/a/42736085/6003870 .
PADYMKO
12
Ну, без преобразования в строку я бы сделал что-то вроде:
def lenDigits(x):"""
Assumes int(x)
"""
x = abs(x)if x <10:return1return1+ lenDigits(x /10)
Как упомянул уважаемый пользователь @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:return1
number = abs(number)if number <=999999999999997:return math.floor(math.log10(number))+1
count =0while number:
count +=1
number //=10return count
Я проверил это на номерах с длиной до 20 (включительно) и все в порядке. Этого должно быть достаточно, поскольку длина целочисленного числа в 64-битной системе равна 19 ( len(str(sys.maxsize)) == 19).
Без сомнения, для потомков самое медленное решение этой проблемы:
def num_digits(num, number_of_calls=1):"Returns the number of digits of an integer num."if num ==0or num ==-1:return1if number_of_calls ==1else0else:return1+ num_digits(num/10, number_of_calls+1)
Предполагая, что вы запрашиваете наибольшее число, которое вы можете сохранить в целом числе, значение зависит от реализации. Я полагаю, что вы не думаете так при использовании Python. В любом случае, довольно большое значение может быть сохранено в «целое число» Python. Помните, Python использует утку печатать!
Изменить:
я дал свой ответ до разъяснения, что спрашивающий хотел количество цифр. Для этого я согласен с методом, предложенным принятым ответом. Больше нечего добавить!
Это можно сделать для целых чисел быстро, используя:
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.
Дэвид Фёрстер
Нет, это не сработает. Если вы превратите 0,17 в целое число, вы получите 0, а длина этого будет отличаться от длины 0,17
Frogboxe
В первом случае, обрезая все от и включая десятичную точку до строкового представления, вы эффективно вычисляете длину целой части числа, что и делает мое предложение. За 0,17 оба решения возвращают 1.
Дэвид Фёрстер
0
Отформатируйте в научной записи и вычеркните экспоненту:
int("{:.5e}".format(1000000).split("e")[1])+1
Я не знаю о скорости, но это просто.
Обратите внимание на количество значащих цифр после десятичной дроби («5» в «.5e» может быть проблемой, если округлить десятичную часть научной нотации до другой цифры. Я установил ее произвольно большим, но мог бы отразить длина наибольшего числа, о котором вы знаете.
Хотя этот код может решить вопрос, в том числе объяснение того, как и почему это решает проблему, действительно поможет улучшить качество вашего сообщения и, вероятно, приведет к большему количеству голосов. Помните, что вы отвечаете на вопрос для читателей в будущем, а не только для того, кто спрашивает сейчас. Пожалуйста, измените свой ответ, чтобы добавить объяснения и указать, какие ограничения и предположения применяются.
Адриан Моль
0
Если вам нужно попросить пользователя ввести данные, а затем подсчитать, сколько там чисел, вы можете выполнить следующее:
count_number = input('Please enter a number\t')print(len(count_number))
Примечание: никогда не принимайте int как пользовательский ввод.
Вы описываете довольно специфический случай, поскольку он на самом деле связан с длиной строки. Кроме того, я мог бы ввести любой нечисловой символ, и вы все равно поверите, что это число.
Бен
0
def digits(n)
count =0if n ==0:return1while(n >=10**count):
count +=1
n += n%10return count
print(digits(25))# Should print 2print(digits(144))# Should print 3print(digits(1000))# Should print 4print(digits(0))# Should print 1
Я должен был указать в случае 1 и 0, потому что log10 (1) = 0 и log10 (0) = ND и, следовательно, указанное условие не выполняется. Однако этот код работает только для целых чисел.
def nbdigit ( x ):if x >=10000000000000000:# 17 -return len( str( x ))if x <100000000:# 1 - 8if x <10000:# 1 - 4if x <100:return(x >=10)+1else:return(x >=1000)+3else:# 5 - 8 if x <1000000:return(x >=100000)+5else:return(x >=10000000)+7else:# 9 - 16 if x <1000000000000:# 9 - 12if x <10000000000:return(x >=1000000000)+9else:return(x >=100000000000)+11else:# 13 - 16if x <100000000000000:return(x >=10000000000000)+13else: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: он не управляет отрицательными числами, но адаптация проста ...
Не вызывайте напрямую специальные методы. Это написано len(str(a)).
Майк Грэм
8
@ ghostdog74 То, что есть электрическая розетка, вовсе не означает, что вы должны в нее сунуть пальцы.
3
так что если вы так против, почему бы вам не сказать мне, что не так с его использованием?
ghostdog74
11
«Магические» ___ методы существуют для внутренних вызовов Python, а не для вашего кода для прямого вызова. Это шаблон Hollywood Framework: не звоните нам, мы вам позвоним. Но цель этого фреймворка заключается в том, что эти магические методы используются стандартными встроенными модулями Python, чтобы ваш класс мог настроить поведение встроенного. Если для вашего кода это метод, вызываемый напрямую, дайте методу имя, отличное от «__». Это четко отделяет те методы, которые предназначены для использования программистом, от методов, которые предоставляются для обратного вызова от встроенных Python.
PaulMcG
7
Это плохая идея, потому что все остальные в известной вселенной используют str () и len (). Это разные вещи ради того, чтобы быть разными, что по своей сути плохо, не говоря уже о том, что это просто ужасно. -1.
Ответы:
Если вы хотите, чтобы длина целого числа была равна числу цифр в целом числе, вы всегда можете преобразовать его в строку типа like
str(133)
и найти ее длину likelen(str(123))
.источник
Math.log10
метод занял всего 7,486343383789062e-05 секунд, примерно в 1501388 раз быстрее!Math.log10
вместо этого.Без преобразования в строку
Также обрабатывать ноль и отрицательные числа
Возможно, вы захотите поместить это в функцию :)
Вот несколько ориентиров. Это
len(str())
уже позади даже для довольно небольших чиселисточник
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 доставят вам проблемы.
math.log10 работает быстро, но создает проблему, когда ваш номер больше 999999999999997. Это потому, что у float слишком много .9s, в результате чего результат округляется.
Решение состоит в том, чтобы использовать метод счетчика while для чисел выше этого порога.
Чтобы сделать это еще быстрее, создайте 10 ^ 16, 10 ^ 17 и так далее и сохраните в виде переменных в списке. Таким образом, это похоже на поиск по таблице.
источник
math.log10
. Интересно посмотреть, как двоичное представление переворачивает значения, давая математически неверный результат.Python
2.*
int
занимает 4 или 8 байтов (32 или 64 бита), в зависимости от вашей сборки Python.sys.maxint
(2**31-1
для 32-битных целых,2**63-1
для 64-битных целых) скажет вам, какая из двух возможностей имеет место.В Python 3
int
s (какlong
s в Python 2) может принимать произвольные размеры вплоть до объема доступной памяти;sys.getsizeof
дает индикацию хорошо для любого заданного значения, хотя это также рассчитывать некоторые фиксированные накладные расходы:Если, как показывают другие ответы, вы думаете о некотором строковом представлении целочисленного значения, то просто возьмите
len
это представление, будь то в базе 10 или иначе!источник
Прошло несколько лет с тех пор, как был задан этот вопрос, но я собрал эталонный тест нескольких методов для вычисления длины целого числа.
(функция libc требует настройки, которую я не включил)
size_exp
спасибо Брайану Преслопски,size_str
спасибо GeekTantra иsize_math
Джону Ла РуиВот результаты:
(Отказ от ответственности: функция запускается на входах от 1 до 1 000 000)
Здесь приведены результаты
sys.maxsize - 100000
дляsys.maxsize
:Как видите,
mod_size
(len("%i" % i)
) является самым быстрым, немного быстрее, чем при использовании,str(i)
и значительно быстрее, чем другие.источник
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(догадываясь, что это так). И это не работает для чисел больше, чемsys.maxsize
потому что числа с плавающей запятой не могут быть "очень большими". Так что любое число выше этого, я думаю, вы застряли с одним из более медленных методов.Пусть число будет
n
тогда количеством цифр вn
выражении:Обратите внимание, что это даст правильные ответы для + 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 .Ну, без преобразования в строку я бы сделал что-то вроде:
Минималистская рекурсия FTW
источник
Подсчитайте количество цифр без преобразования целого числа в строку:
источник
Как упомянул уважаемый пользователь @Calvintwr, у функции
math.log10
есть проблема с числом вне диапазона [-999999999999997, 999999999999997], где мы получаем ошибки с плавающей запятой. У меня была эта проблема с JavaScript (Google V8 и NodeJS) и C (компилятор GNU GCC), поэтому'purely mathematically'
решение здесь невозможно.Основываясь на этой сути и ответе уважаемый пользователь @Calvintwr
Я проверил это на номерах с длиной до 20 (включительно) и все в порядке. Этого должно быть достаточно, поскольку длина целочисленного числа в 64-битной системе равна 19 (
len(str(sys.maxsize)) == 19
).Все примеры кодов, протестированных на Python 3.5
источник
Без сомнения, для потомков самое медленное решение этой проблемы:
источник
источник
Предполагая, что вы запрашиваете наибольшее число, которое вы можете сохранить в целом числе, значение зависит от реализации. Я полагаю, что вы не думаете так при использовании Python. В любом случае, довольно большое значение может быть сохранено в «целое число» Python. Помните, Python использует утку печатать!
Изменить: я дал свой ответ до разъяснения, что спрашивающий хотел количество цифр. Для этого я согласен с методом, предложенным принятым ответом. Больше нечего добавить!
источник
источник
Это можно сделать для целых чисел быстро, используя:
Который получает длину строки абсолютного значения "1234567890"
abs
возвращает число БЕЗ каких-либо отрицательных значений (только величину),str
приводит к преобразованию / преобразованию его в строку иlen
возвращает длину строки этой строки.Если вы хотите, чтобы он работал для поплавков, вы можете использовать одно из следующих:
Для дальнейшего использования.
источник
int
), чем усечь его десятичное строковое представление:len(str(abs(int(0.1234567890))))
возвращает 1.Отформатируйте в научной записи и вычеркните экспоненту:
Я не знаю о скорости, но это просто.
Обратите внимание на количество значащих цифр после десятичной дроби («5» в «.5e» может быть проблемой, если округлить десятичную часть научной нотации до другой цифры. Я установил ее произвольно большим, но мог бы отразить длина наибольшего числа, о котором вы знаете.
источник
источник
Если вам нужно попросить пользователя ввести данные, а затем подсчитать, сколько там чисел, вы можете выполнить следующее:
Примечание: никогда не принимайте int как пользовательский ввод.
источник
источник
Мой код для того же выглядит следующим образом, я использовал метод log10:
def digit_count (число):
Я должен был указать в случае 1 и 0, потому что log10 (1) = 0 и log10 (0) = ND и, следовательно, указанное условие не выполняется. Однако этот код работает только для целых чисел.
источник
Вот громоздкая, но быстрая версия:
Всего 5 сравнений для не слишком больших чисел. На моем компьютере она примерно на 30% быстрее, чем
math.log10
версия, и на 5% быстрее, чем версияlen( str())
. Хорошо ... не так привлекательно, если вы не используете его неистово.И вот набор чисел, которые я использовал для проверки / измерения моей функции:
NB: он не управляет отрицательными числами, но адаптация проста ...
источник
источник
len(str(a))
.