Как узнать длину числа в python
Перейти к содержимому

Как узнать длину числа в python

  • автор:

Функция len() в Python, количество элементов объекта

Количество элементов в последовательности или коллекции

Синтаксис:
len(s) 
Параметры:
  • s — последовательность или коллекция.
Возвращаемое значение:
Описание:

Функция len() возвращает длину (количество элементов) в объекте.

Аргумент может быть последовательностью, такой как строка, байты, кортеж, список или диапазон или коллекцией (такой как словарь, множество или неизменяемое множество).

Когда объект является строкой, функция len() возвращает количество символов в строке (строка представляет собой частный случай кортежа Python).

Пользовательские типы данных могут определять метод __len__() , значение из которого, будет возвращено при вызове функции len() .

Примеры подсчета количества элементов в последовательности.

Что можно подсчитать:

  • число элементов в списке;
  • число элементов в кортеже;
  • число символов в строке (длина строки);
  • количество байтов в строке;
  • число элементов в множестве;
  • число пар ключ-значение в словаре;

Подсчет элементов списка.

# подсчет количества элементов списка >>> mylist = ['apple', 'banana', 'cherry'] >>> len(mylist) # 3 

Подсчет количества символов в строке (длина строки).

# подсчет символов в строке >>> string = 'Hello' >>> len(string) # 5 >>> len('абракадабра') # 11 

Подсчет количества байтов в строке.

# подсчет символов в строке >>> line_en = 'Hello'.encode('utf-8') >>> line_ru = 'Привет'.encode('utf-8') >>> len(line_en) # 5 >>> len(line_ru) # 12 

Подсчет количества ключей словаря.

# подсчет количества ключей словаря. >>> d = 'a': 1, 'b': 1, 'c': 1, 'd': 1> >>> keys = list(d) >>> len(keys) # 4 

Другие паттерны использования функции len() .

Проверка списка на дублирующие значения:

Чтобы проверить уникальность значений списка достаточно сравнить количество элементов списка с количеством элементов множества этого списка. Используя тот факт, что множество set() содержит только уникальные элементы.

>>> lst = [1, 2, 3, 4, 5, 6] # список с уникальными значениями >>> len(lst) == len(set(lst)) # True >>> lst.append(3) >>> lst # [1, 2, 3, 4, 5, 6, 3] # в списке есть повторы >>> len(lst) == len(set(lst)) # False 

Использование функции len() для подчеркивания строки:

>>> mystr = "Привет Python!" >>> underline = '-' * len(mystr) >>> print(f'mystr>\nunderline>') # Привет Python! # -------------- 

Использование функции len() в итерации по индексам последовательности:

Это пример — как один из вариантов получения индексов элементов списка. Конечно, для этой цели лучше использовать встроенную функцию enumerate() , т.к. сразу можно получить и индекс элемента и его значение.

>>> mylist = ['apple', 'banana', 'cherry', 'pear', 'plum'] >>> for i in range(len(mylist)): . print(i, mylist[i]) . # 0 apple # 1 banana # 2 cherry # 3 pear # 4 plum 

Использование встроенной функции enumerate() для получения индексов элементов:

>>> mylist = ['apple', 'banana', 'cherry', 'pear', 'plum'] >>> for i, item in enumerate(mylist): . print(i, item) . # 0 apple # 1 banana # 2 cherry # 3 pear # 4 plum 

По индексам последовательности, конечно удобнее итерироваться при помощи функции enumerate() .

Подсчет количества цифр в числе (длина числа)

Для того, чтобы посчитать количество цифр в числе необходимо сначала перевести число float или int в любую последовательность, например в строку, а затем к последовательности применить функцию len() , что бы получить количество элементов.

Для получения строкового представления объектов float и int , применим к ним функцию str.

Пример получения длины целого числа:

# получение длины целого числа >>> x = 1235412687 >>> str_x = str(x) >>> str_x # '1235412687' >>> num_x = len(str_x) >>> num_x # 10 

Так как вещественные числа в Python имеют запятую, то количество цифр в числе float будет на 1 меньше, а именно len(str(float)) — 1 .

Пример получения длины вещественного числа:

# получение длины вещественного числа >>> x = 0.1230541287 # запишем преобразования короче >>> num_x = len(str(x)) - 1 >>> num_x # 11 

Чтобы получить количество уникальных цифр в числе, необходимо строковое представление числа преобразовать в множество set , т.к. множество представляет собой последовательность неповторяющихся элементов.

Пример подсчета уникальных цифр в числах float и int :

# получение кол-ва уникальных цифр целого числа >>> x = 1235412687 # получаем строковое представление >>> str_x = str(x) # получаем множество уникальных цифр числа >>> set_x = set(str_x) # # считаем кол-во уникальных цифр >>> num_x = len(set_x) >>> num_x # 8 # для получения кол-ва уникальных цифр # числа `float` сделаем запись короче >>> x = 0.1230541287 # количество уникальных цифр числа `float` # будет на 1 меньше, т.к. число имеет разделитель >>> num_x = len(set(str(x))) - 1 # 8 
  • ОБЗОРНАЯ СТРАНИЦА РАЗДЕЛА
  • Функция abs(), абсолютное значение числа
  • Функция all(), все элементы True
  • Функция any(), хотя бы один элемент True
  • Функция ascii(), преобразует строку в ASCII
  • Функция bin(), число в двоичную строку
  • Класс bool(), логическое значение объекта
  • Функция breakpoint(), отладчик кода
  • Класс bytearray(), преобразует в массив байтов
  • Класс bytes(), преобразует в строку байтов
  • Функция callable(), проверяет можно ли вызвать объект
  • Функция chr(), число в символ Юникода
  • Класс classmethod, делает функцию методом класса
  • Функция compile() компилирует блок кода Python
  • Класс complex(), преобразует в комплексное число
  • Функция delattr(), удаляет атрибут объекта
  • Класс dict() создает словарь
  • Функция dir(), все атрибуты объекта
  • Функция divmod(), делит числа с остатком
  • Функция enumerate(), счетчик элементов последовательности
  • Функция eval(), выполняет строку-выражение с кодом
  • Функция exec(), выполняет блок кода
  • Функция filter(), фильтрует список по условию
  • Класс float(), преобразует в вещественное число
  • Функция format(), форматирует значение переменной
  • Класс frozenset(), преобразует в неизменяемое множество
  • Функция getattr(), значение атрибута по имени
  • Функция globals(), переменные глобальной области
  • Функция hasattr(), наличие атрибута объекта
  • Функция hash(), хэш-значение объекта
  • Функция help(), справка по любому объекту
  • Функция hex(), число в шестнадцатеричную строку
  • Функция id(), идентификатор объекта
  • Функция input(), ввод данных с клавиатуры
  • Класс int(), преобразует в тип int
  • Функция isinstance(), принадлежность экземпляра к классу
  • Функция issubclass(), проверяет наследование класса
  • Функция iter(), создает итератор
  • Функция len(), количество элементов объекта
  • Класс list(), преобразовывает в список
  • Функция locals(), переменные локальной области
  • Функция map(), обработка последовательности без цикла
  • Функция max(), максимальное значение элемента
  • Класс memoryview(), ссылка на буфер обмена
  • Функция min(), минимальное значение элемента
  • Функция next(), следующий элемент итератора
  • Класс object(), возвращает безликий объект
  • Функция oct(), число в восьмеричную строку
  • Функция open(), открывает файл на чтение/запись
  • Функция ord(), число символа Unicode
  • Функция pow(), возводит число в степень
  • Функция print(), печатает объект
  • Класс property(), метод класса как свойство
  • Класс range(), генерирует арифметические последовательности
  • Функция repr(), описание объекта
  • Функция reversed(), разворачивает последовательность
  • Функция round(), округляет число
  • Класс set(), создает или преобразовывает в множество
  • Функция setattr(), создает атрибут объекта
  • Класс slice(), шаблон среза
  • Функция sorted(), выполняет сортировку
  • Декоратор staticmethod(), метод класса в статический метод
  • Класс str(), преобразует объект в строку
  • Функция sum(), сумма последовательности
  • Функция super(), доступ к унаследованным методам
  • Класс tuple(), создает или преобразует в кортеж
  • Класс type(), возвращает тип объекта
  • Функция vars(), словарь переменных объекта
  • Функция zip(), объединить элементы в список кортежей
  • Функция __import__(), находит и импортирует модуль
  • Функция aiter(), создает асинхронный итератор
  • Функция anext(), следующий элемент асинхронного итератора

Как в Python реализованы очень длинные числа типа integer?

Когда вы пишете на низкоуровневом языке, таком как С, вы беспокоитесь о выборе правильного типа данных и спецификаторах для ваших целых чисел, на каждом шаге анализируете достаточно ли будет использовать просто int или нужно добавить long или даже long double . Однако при написании кода на Python вам не нужно беспокоиться об этих «незначительных» вещах, потому что Python может работать с числами типа integer любого размера.

В С, если вы попытаетесь вычислить 2 20000 с помощью встроенной функции powl , то на выходе получите inf .

#include #include int main(void) < printf("%Lf\n", powl(2, 20000)); return 0; >$ ./a.out inf

Но в Python сделать это проще простого:

>>> 2 ** 20000 39802768403379665923543072061912024537047727804924259387134 . . . 6021 digits long . . 6309376

Должно быть под капотом Python делает что-то очень красивое и сегодня мы узнаем, что именно он делает, чтобы работать с целыми числами произвольного размера!

Представление и определение

Integer в Python это структура C, определенная следующим образом:

struct _longobject < PyObject_VAR_HEAD digit ob_digit[1]; >; 

PyObject_VAR_HEAD – это макрос, он раскрывается в PyVarObject , который имеет следующую структуру:

typedef struct < PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ >PyVarObject;

Другие типы, у которых есть PyObject_VAR_HEAD :

  • PyBytesObject
  • PyTupleObject
  • PyListObject
struct _longobject < PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ digit ob_digit[1]; >;

В структуре PyObject есть некоторые мета-поля, используемые для подсчета ссылок (сборки мусора), но для того, чтобы поговорить об этом нужна отдельная статья. Поле, на котором мы сосредоточимся это ob_digit и в немного ob_size .

Расшифровка ob_digit

ob_digit – это статически аллоцированый массив единичной длины типа digit (typedef для uint32_t) . Поскольку это массив, ob_digit в первую очередь является указателем на число, и, следовательно, при необходимости он может быть увеличен с помощью функции malloc до любой длины. Таким образом python может представлять и обрабатывать очень длинные числа.

Как правило в низкоуровневых языках, таких как С, точность целых чисел ограничена 64-битами, однако Python поддерживает целые числа произвольной точности. Начиная с версии Python 3, все числа представлены в виде bignum и ограничены только доступной памятью системы.

Расшифровка ob_size

ob_size хранит количество элементов в ob_digit . Python переопределяет и затем использует значение ob_size для определения фактического количества элементов, содержащихся в массиве, чтобы повысить эффективность выделения памяти массиву ob_digit .

Хранение

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

С таким подходом число 5238 будет сохранено так:

Такой подход неэффективен, поскольку мы будем использовать до 32-бит цифр (uint32_t) для хранения десятичной цифры, которая, по сути, колеблется от 0 до 9 и может быть легко представлена всего лишь 4 битами, ведь при написании чего-то столь же универсального как python, разработчик ядра должен быть еще изобретательнее.

Итак, можем ли мы сделать лучше? Конечно, иначе я бы не выложил эту статью. Давайте подробнее рассмотрим то, как Python хранит сверхдлинное целое число.

Путь Python

Вместо того, чтобы хранить только одну десятичную цифру в каждом элементе массива ob_digit , Python преобразует числа из системы счисления с основанием 10 в числа в системе с основанием 2 30 и вызывает каждый элемент, как цифру, значение которой колеблется от 0 до 2 30 — 1.

В шестнадцатеричной системе счисления, основание 16 ~ 2 4 означает, что каждая «цифра» шестнадцатеричного числа колеблется от 0 до 15 в десятичной системе счисления. В Python аналогично, «число» с основанием 2 30 , что означает, что число будет варьироваться от 0 до 2 30 – 1 = 1073741823 в десятичной системе счисления.

Таким образом, Python эффективно использует почти все выделенное пространство в 32 бита на одну цифру, экономит ресурсы и все еще выполняет простые операции, такие как сложение и вычитание на уровне математики начальной школы.

В зависимости от платформы Python использует либо 32-битные целочисленные беззнаковые массивы, либо 16-битные целочисленные беззнаковые массивы с 15-битными цифрами. Для выполнения операций, которые будут рассмотрены дальше, понадобится всего несколько битов.

Пример: 1152921504606846976

Как уже упоминалось, для Python числа представлены в системе с основанием 2 30 , то есть если вы конвертируете 1152921504606846976 в систему счисления с основанием 2 30 , вы получите 100.

1152921504606846976 = 1 * (2 30 ) 2 + 0 * (2 30 ) 1 + 0 * (2 30 ) 0

Поскольку ob_digit первым хранит наименее значащую цифру, оно сохраняется как 001 в виде трех цифр.

Структура _longobject для этого значения будет содержать:

  • ob_size как 3
  • ob_digit как [0, 0, 1]

Я создал демонстрационный REPL, который покажет, как внутри себя Python хранит integer, а также ссылается на члены структуры, такие как ob_size , ob_refcount и т. д.

Операции над длинными числами типа integer

Теперь, когда у нас есть четкое представление о том, как Python реализует целые числа произвольной точности, настало время понять, как с ними выполняются различные математические операции.

Сложение

Целые числа хранятся «в цифрах», это означает, что сложение выполняется также просто, как в начальной школе, и исходный код Python показывает нам, что именно так сложение и реализовано. Функция с именем x_add в файле longobject.c выполняет сложение двух чисел.

. for (i = 0; i < size_b; ++i) < carry += a->ob_digit[i] + b->ob_digit[i]; z->ob_digit[i] = carry & PyLong_MASK; carry >>= PyLong_SHIFT; > for (; i < size_a; ++i) < carry += a->ob_digit[i]; z->ob_digit[i] = carry & PyLong_MASK; carry >>= PyLong_SHIFT; > z->ob_digit[i] = carry; . 

Приведенный выше фрагмент кода взят из функции x_add . Как видите, она перебирает число по цифрам и выполняет сложение цифр, вычисляет результат и добавляет перенос.

Интереснее становится, когда результатом сложения является отрицательное число. Знак ob_size является знаком integer’а, то есть, если у вас есть отрицательное число, то ob_size будет минусом. Значение ob_size по модулю будет определять количество цифр в ob_digit .

Вычитание

Подобно тому, как происходит сложение, происходит и вычитание. Функция с именем x_sub в файле longobject.c выполняет вычитание одного числа из другого.

. for (i = 0; i < size_b; ++i) < borrow = a->ob_digit[i] - b->ob_digit[i] - borrow; z->ob_digit[i] = borrow & PyLong_MASK; borrow >>= PyLong_SHIFT; borrow &= 1; /* Keep only one sign bit */ > for (; i < size_a; ++i) < borrow = a->ob_digit[i] - borrow; z->ob_digit[i] = borrow & PyLong_MASK; borrow >>= PyLong_SHIFT; borrow &= 1; /* Keep only one sign bit */ > . 

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

Умножение

И снова умножение будет реализовано тем же наивным способом, который мы узнали из уроков математики в начальной школе, но он не отличается эффективностью. Чтобы поддерживать эффективность, Python реализует алгоритм Карацубы, который умножает два n-значных числа за O( n log 2 3 ) простых шагов.

Алгоритм непростой и его реализация выходит за рамки данной статьи, но вы можете найти его реализацию в функциях k_mul и k_lopsided_mul в файле longobject.c .

Деление и другие операции

Все операции над целыми числами определены в файле longobject.c , их очень просто найти и проследить работу каждой. Внимание: Детальное понимание работы каждой из них займет время, поэтому заранее запаситесь попкорном.

Оптимизация часто используемых целых чисел

Python заранее выделяет в памяти небольшое количество целых чисел в диапазоне от -5 до 256. Это выделение происходит во время инициализации, и поскольку мы не можем изменить целые числа (иммутабельность), эти предварительно выделенные числа являются синглтонами и на них ссылаются напрямую вместо реаллокации. Это значит, что каждый раз, когда мы используем/создаем маленькое число, Python вместо реаллокации просто возвращает ссылку на предварительно аллоцированное число.

Такую оптимизацию можно проследить в макросе IS_SMALL_INT и функции get_small_int в longobject.c . Так Python экономит много места и времени на вычисление часто используемых чисел типа integer.

Это вторая статья из серии Python Internals. Первая статья была о том, как я изменил свою версию Python, сделав его двусмысленным. Она поможет вам сделать первые шаги в понимании исходного кода Python и продолжить путь к становлению разработчиком ядра Python.

Если вы хотите увидеть больше похожих статей, подпишитесь на мою рассылку и получайте их прямо в свой почтовый ящик. Я пишу об инженерии, системном проектировании и немного о программировании каждую пятницу. Пишите мне на @arpit_bhayani. Мои предыдущие статьи вы найдете на @arpitbhayani.me/blogs.

На этом все. До встречи на курсе!

  • programming
  • python
  • python internals
  • Блог компании OTUS
  • Python
  • Программирование

поиск минимального и максимального по критерию длины числа python

Дана последовательность чисел, завершающаяся числом 0. Найдите самое короткое и длинное число из введенных. Для вычисления длины числа, нахождения минимума и максимума используйте отдельные функции. Формат входных данных: Вводится последовательность целых чисел, оканчивающаяся числом 0 (само число 0 в последовательность не входит, а служит как признак ее окончания).

def count_digits(num): count = 0 while num: num //= 10 count += 1 return count def min_max(num, count): num_len = count max_len, min_len = -1, 99999999 min_num, max_num = None, None if num_len > max_len: max_len = num_len max_num = num if num_len < min_len: min_len = num_len min_num = num print(min_num, max_num) while True: num = int(input()) if num == 0: break count = count_digits(num) min_max(num, count) 

Не могу понять, в чем проблема, если например просто использовать поиск максимума, т.е убирать в функции часть с посиком минимума, все хорошо.. Не могу понять, где спотыкаюсь.

Отслеживать
задан 21 ноя 2021 в 13:38
113 3 3 бронзовых знака

по заданию оценить самое длиное и короткое через длину числа, я понимаю, что простое сравнение даст верный результат

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *