Длина целого числа в Python


233

В Python, как найти количество цифр в целом числе?


1
Я не понимаю твой вопрос. Вы имели в виду размер целого числа? Хотите узнать количество цифр? Просьба уточнить.
— Batbrat

Ответы:


317

Если вы хотите, чтобы длина целого числа была равна числу цифр в целом числе, вы всегда можете преобразовать его в строку типа like str(133)и найти ее длину like len(str(123)).


18
Конечно, если вы ищете количество цифр, это даст слишком большой результат для отрицательных чисел, поскольку он будет считать отрицательный знак.
— Крис Апчерч

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))+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 для этого является решением математика; Использование 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 и так далее и сохраните в виде переменных в списке. Таким образом, это похоже на поиск по таблице.

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: И величины медленнее
— Чайтанья Бангера

«Опасно полагаться на операции с плавающей запятой, дающие точные результаты», - Марк Дикинсон, член основной команды разработчиков 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дает индикацию хорошо для любого заданного значения, хотя это также рассчитывать некоторые фиксированные накладные расходы:

>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28

Если, как показывают другие ответы, вы думаете о некотором строковом представлении целочисленного значения, то просто возьмите 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 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 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 или 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:
        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

Хороший избегает преобразования строк полностью.
— Патрик Мутуку

8

Как упомянул уважаемый пользователь @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


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. Помните, 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.
— Дэвид Фёрстер

Нет, это не сработает. Если вы превратите 0,17 в целое число, вы получите 0, а длина этого будет отличаться от длины 0,17
— Frogboxe

В первом случае, обрезая все от и включая десятичную точку до строкового представления, вы эффективно вычисляете длину целой части числа, что и делает мое предложение. За 0,17 оба решения возвращают 1.
— Дэвид Фёрстер

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

Хотя этот код может решить вопрос, в том числе объяснение того, как и почему это решает проблему, действительно поможет улучшить качество вашего сообщения и, вероятно, приведет к большему количеству голосов. Помните, что вы отвечаете на вопрос для читателей в будущем, а не только для того, кто спрашивает сейчас. Пожалуйста, измените свой ответ, чтобы добавить объяснения и указать, какие ограничения и предположения применяются.
— Адриан Моль

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)).
— Майк Грэм

8
@ ghostdog74 То, что есть электрическая розетка, вовсе не означает, что вы должны в нее сунуть пальцы.

3
так что если вы так против, почему бы вам не сказать мне, что не так с его использованием?
— ghostdog74

11
«Магические» ___ методы существуют для внутренних вызовов Python, а не для вашего кода для прямого вызова. Это шаблон Hollywood Framework: не звоните нам, мы вам позвоним. Но цель этого фреймворка заключается в том, что эти магические методы используются стандартными встроенными модулями Python, чтобы ваш класс мог настроить поведение встроенного. Если для вашего кода это метод, вызываемый напрямую, дайте методу имя, отличное от «__». Это четко отделяет те методы, которые предназначены для использования программистом, от методов, которые предоставляются для обратного вызова от встроенных Python.
— PaulMcG

7
Это плохая идея, потому что все остальные в известной вселенной используют str () и len (). Это разные вещи ради того, чтобы быть разными, что по своей сути плохо, не говоря уже о том, что это просто ужасно. -1.
— Гленн Мейнард
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.