Получение целочисленной части числа в Python (truncation)
Способы получения целой части числа
Наиболее эффективное решение: функция int()
Функция int() для чисел с плавающей точкой возвращает целое число путем отбрасывания дробной части. Это так называемое усечение (truncation) к нулю. Для положительных чисел результат совпадает с floor, для отрицательных с ceil (так как отбрасывание отрицательной части приближает к нулю).
# Положительное число
a = 5.99
print(int(a)) # 5
Python целая часть числа (целая часть числа в python)
5
Python округление в большую (округление числа в большую сторону в python)
# Отрицательное число
b = -5.99
print(int(b)) # -5
-5
Функция int() работает быстро, так как реализована на C. Она также подходит для строк, но здесь рассматривается работа с числами.
Как получить целую часть с помощью math.trunc()?
Модуль math предоставляет функцию trunc(), которая делает то же самое, что и int(): отбрасывает дробную часть. Разница в том, что math.trunc() может быть переопределена для пользовательских типов, но для стандартных чисел она идентична int().
import math
print(math.trunc(5.99)) # 5
print(math.trunc(-5.99)) # -5
5 -5
Когда стоит отдать предпочтение math.trunc?
Если код использует множество функций из math, применение trunc повышает читаемость. Однако int() короче и не требует импорта.
Как оператор // связан с целой частью числа?
Оператор целочисленного деления // возвращает результат деления, округленный вниз (floor). Для положительных чисел это эквивалентно отбрасыванию дробной части. Но для отрицательных чисел // дает число, меньшее или равное точному частному, что отличается от усечения.
print(7 // 2) # 3
print(-7 // 2) # -4
print(int(-7/2)) # -3
3 -4 -3
В каких случаях // подходит для получения целой части?
Если требуется целая часть от деления в математическом смысле (округление вниз), // является правильным выбором. Например, при вычислении индексов или делении массивов.
Почему round() не подходит для получения целой части?
Функция round(x) округляет число до ближайшего целого, а при равной удаленности до четного. Это не отбрасывание дробной части.
print(round(3.5)) # 4
print(int(3.5)) # 3
print(round(2.5)) # 2
print(int(2.5)) # 2
4 3 2 2
Для получения целой части round() не используется.
Как получить целую часть через разность с дробной частью (math.modf)?
Функция math.modf разбивает число на целую и дробную части, возвращая кортеж (дробная, целая).
import math
frac, whole = math.modf(5.99)
print(whole) # 5.0, но float
print(int(whole)) # 5
5.0 5
Этот способ менее удобен, так как целая часть возвращается как float.
Возможно ли получение целой части через строковое представление?
Можно преобразовать число в строку, разделить по точке и взять первую часть. Однако это неэффективно и работает только для положительных чисел (для отрицательных нужно учитывать знак).
x = 5.99
str_x = str(x)
int_part = int(str_x.split('.')[0])
print(int_part) # 5
5
Такой метод не рекомендуется для серьезных вычислений.
Как работают math.floor() и math.ceil() для отрицательных чисел?
Для полноты стоит упомянуть, что floor() возвращает наибольшее целое, не превышающее число, а ceil() наименьшее целое, не меньшее числа. Для положительных чисел floor() совпадает с int(), для отрицательных отличается.
import math
print(math.floor(-3.14)) # -4
print(math.ceil(-3.14)) # -3
print(int(-3.14)) # -3
-4 -3 -3
Эти функции не дают целую часть числа в смысле truncation.
Типичные ошибки и проблемы
1. Использование // для отбрасывания дробной части отрицательных чисел приводит к неожиданному результату. Ошибка возникает, если программист ожидает от // усечение, а получает округление вниз.
value = -3.14
wrong = value // 1 # даст -4.0
print(wrong) # -4.0
2. Путаница между int() и round(). При работе с числами, заканчивающимися на .5, round дает ближайшее четное, что может быть не тем, что нужно.
3. Использование math.floor() для отбрасывания дробной части отрицательных чисел. Результат будет на единицу меньше ожидаемого (для -3.14 floor дает -4 вместо -3).
Чтобы избежать этих проблем, необходимо четко определять нужный тип округления. Если требуется отбросить дробную часть (усечение к нулю), используйте int() или math.trunc().
Пример 1: Обработка отрицательных чисел различными методами
Демонстрация отличий int(), math.trunc(), math.floor(), math.ceil() и // для отрицательных чисел.
import math
nums = [3.14, -3.14, 5.99, -5.99]
for n in nums:
print(f'{n:>7} -> int: {int(n):2} trunc: {math.trunc(n):2} floor: {math.floor(n):2} ceil: {math.ceil(n):2} //1: {n//1:5.1f}')
3.14 -> int: 3 trunc: 3 floor: 3 ceil: 4 //1: 3.0 -3.14 -> int: -3 trunc: -3 floor: -4 ceil: -3 //1: -4.0 5.99 -> int: 5 trunc: 5 floor: 5 ceil: 6 //1: 5.0 -5.99 -> int: -5 trunc: -5 floor: -6 ceil: -5 //1: -6.0
Пример 2: Получение целой части для элементов списка с помощью map
Применение int() ко всем элементам списка чисел с плавающей точкой.
values = [1.1, 2.7, 3.4, -4.9, -5.0]
int_parts = list(map(int, values))
print(int_parts)
[1, 2, 3, -4, -5]
Пример 3: Сравнение производительности int() и math.trunc()
Использование timeit для оценки скорости.
import math, timeit
setup = 'import math; x = 3.14159'
t_int = timeit.timeit('int(x)', setup, number=1000000)
t_trunc = timeit.timeit('math.trunc(x)', setup, number=1000000)
print(f'int: {t_int:.3f} sec')
print(f'trunc: {t_trunc:.3f} sec')
int: 0.134 sec trunc: 0.142 sec
В данном тесте int() немного быстрее, но разница незначительна.
Пример 4: Использование Decimal для точного отбрасывания дробной части
Модуль decimal позволяет контролировать точность и способ округления. Для усечения (truncation) используется метод quantize с округлением ROUND_DOWN.
from decimal import Decimal, ROUND_DOWN
x = Decimal('3.1415926535')
truncated = x.quantize(Decimal('1'), rounding=ROUND_DOWN)
print(truncated) # 3
3
Этот способ полезен, когда важна точность представления (например, финансовые расчеты).
Пример 5: Получение целой части от деления с остатком (divmod)
Функция divmod возвращает пару (частное, остаток). Частное является целой частью от деления с округлением вниз.
quotient, remainder = divmod(17, 3)
print(quotient, remainder) # 5 2
# Для отрицательных:
quot2, rem2 = divmod(-17, 3)
print(quot2, rem2) # -6 1 (так как floor division)
5 2 -6 1
divmod часто используется в алгоритмах, где нужна целая часть частного и остаток одновременно.
Пример 6: Использование NumPy для массивов чисел
Библиотека NumPy предоставляет функцию np.trunc(), которая поэлементно отбрасывает дробную часть.
import numpy as np
arr = np.array([1.5, -2.7, 3.0, -4.1])
trunc_arr = np.trunc(arr)
print(trunc_arr)
[ 1. -2. 3. -4.]
Функция np.trunc эквивалентна int() для каждого элемента, но возвращает массив с плавающей точкой. Для получения целочисленного массива используйте np.trunc(arr).astype(int).