Длина целого числа в Python - PullRequest
184 голосов
/ 03 февраля 2010

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

Ответы [ 16 ]

240 голосов
/ 03 февраля 2010

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

199 голосов
/ 03 февраля 2010

Без преобразования в строку

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
30 голосов
/ 05 марта 2015

Все решения 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
21 голосов
/ 03 февраля 2010

Python 2.* int s занимает 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 дает вам хорошее указание для любого заданного значения, хотя оно действительно также учитывает некоторые фиксированные издержки:

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

Если, как показывают другие ответы, вы думаете о некотором строковом представлении целочисленного значения, просто возьмите len этого представления, будь то в базе 10 или иначе!

13 голосов
/ 18 сентября 2015

Ну, без преобразования в строку я бы сделал что-то вроде:

def lenDigits(x): 
    """
    Assumes int(x)
    """

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

Минималистская рекурсия FTW

13 голосов
/ 09 октября 2011

Пусть число будет n, тогда количество цифр в n определяется как:

math.floor(math.log10(n))+1

Обратите внимание, что это даст правильные ответы для + ve целых чисел <10e15. Помимо этого, пределы точности типа возврата <code>math.log10 вступают в силу, и ответ может быть отключен на 1. Я бы просто использовал len(str(n)) сверх этого; для этого требуется O(log(n)) время, которое равняется итерации по степеням 10.

Спасибо @SetiVolkylany за мое внимание к этому ограничению. Удивительно, как на первый взгляд правильные решения имеют недостатки в деталях реализации.

5 голосов
/ 05 января 2019

Прошло несколько лет с тех пор, как был задан этот вопрос, но я собрал эталонный тест нескольких методов для вычисления длины целого числа.

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), и значительно быстрее, чем другие.

5 голосов
/ 11 марта 2017

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

Для потомков, без сомнения, самое медленное решение этой проблемы:

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)
2 голосов
/ 16 июля 2010
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...