Как определить длину числа?
Что проверяют
Не столько сам приём, сколько внимание к краевым случаям: ноль, минус, очень большие и дробные числа. Следом просят сравнить способы по скорости и спрашивают, почему логарифм иногда ошибается.
Как отвечать
Сначала уточните, что считать длиной: количество цифр или количество символов в записи. Для -678 это 3 или 4, и оба ответа верны при своей постановке.
- через строку:
len(str(abs(n))). Самый читаемый вариант и для обычных чисел быстрый, потому что преобразование написано на C. Для нуля даёт 1, знак убираетabs; - через логарифм:
math.floor(math.log10(abs(n))) + 1. Ноль обрабатывают отдельно, иначеValueError. Главная проблема:log10считает во float и на больших числах ошибается. Для числа из пятнадцати девяток он возвращает ровно15.0, и функция отвечает 16 вместо 15; - циклом: делить на 10 через
//=, пока число не станет нулём. Это O(k) по числу цифр и заметно медленнее строки, зато годится, если строки запретили; - гигантские числа: в актуальных версиях Python
str()для целого длиннее 4300 цифр падает сValueError, это защита от DoS. Лимит меняют черезsys.set_int_max_str_digits(), а быструю оценку даётn.bit_length() * math.log10(2); - дробные:
len(str(0.1 + 0.2))вернёт 19, потому что это0.30000000000000004, аstr(1e16)даёт'1e+16'. Здесь без уточнения задачи иdecimal.Decimalне обойтись.
Хороший финал: для типичных задач строка, без строк цикл, логарифм только с оговоркой про точность.
Где спотыкаются
Забывают про ноль и отрицательные числа. Логарифм от нуля падает, цикл while n > 0 для нуля возвращает 0, а для отрицательного числа не выполняется вовсе.
Называют логарифм самым быстрым и правильным способом. Он действительно работает за константу, но ломается у границы степеней десяти.
Не уточняют задачу и молча считают минус цифрой или, наоборот, теряют его, когда нужна была длина строки.