Дробная часть float: методы и примеры на Python
Способы получения дробной части числа с плавающей точкой
Дробная часть числа float часто требуется для математических вычислений, финансовых расчётов или форматирования вывода. В Python есть несколько подходов, каждый со своими особенностями, точностью и поведением для отрицательных чисел, бесконечностей и NaN.
Основное решение: math.modf()
Функция math.modf(x) возвращает кортеж из двух элементов: дробная часть и целая часть. Обе части имеют тип float, причём дробная часть сохраняет знак исходного числа.
import math
value = 3.1415
frac, whole = math.modf(value)
print(f"Дробная: {frac}, Целая: {whole}")Python дробная часть float (дробная часть числа float в python)
Дробная: 0.14149999999999996, Целая: 3.0
Этот метод быстрый, встроенный и подходит для большинства задач. Однако из-за двоичного представления чисел с плавающей точкой результат может содержать небольшие погрешности (как 0.1415 превратилось в 0.141499…). Для отрицательных чисел дробная часть также отрицательна:
print(math.modf(-1.7))(-0.7000000000000002, -1.0)
Как получить всегда положительную дробную часть?
Если требуется дробная часть в диапазоне [0, 1), используется оператор остатка от деления на 1: x % 1. Для отрицательных чисел он возвращает положительный остаток (например, -1.3 % 1 = 0.7).
values = [3.14, -1.3, 0.0]
for v in values:
frac = v % 1
print(f"{v:5} -> {frac:.10f}")3.14 -> 0.1400000000 -1.30 -> 0.7000000000 0.00 -> 0.0000000000
Цель: получение модуля дробной части, например для отображения времени (часы:минуты).
Проблема:
Для NaN и Inf оператор % 1 ведёт себя неопределённо:
import math
print(math.nan % 1, math.inf % 1)nan nan
Результат - nan. Следует проверять на бесконечность и NaN перед использованием.
Как получить дробную часть через вычитание целой?
Стандартное вычитание x - int(x) даёт результат, аналогичный math.modf (дробная часть со знаком числа).
frac = 3.14 - int(3.14)
print(frac) # 0.14000000000000012Для отрицательных чисел int(-1.3) равно -1, поэтому дробная часть получается отрицательной: -0.3.
Цель: простой и понятный код без импортов.
Ошибка:
Для больших чисел, выходящих за пределы точности int (больше 2^53), преобразование теряет точность. Используйте math.modf или Decimal.
Как получить дробную часть с высокой точностью?
Для финансовых или научных расчётов, где критична точность десятичных дробей, применяется модуль decimal.Decimal. Он позволяет точно представить дробную часть без погрешностей двоичной арифметики.
from decimal import Decimal, getcontext
getcontext().prec = 28 # количество знаков
d = Decimal('3.1415')
frac = d % 1
print(frac) # 0.1415Цель: исключение ошибок округления, работа с денежными суммами.
Проблема:
Производительность ниже, чем у float; необходимо явно задавать точность и передавать числа строками.
Как получить дробную часть с помощью math.floor?
Для положительных чисел x - math.floor(x) даёт дробную часть. Для отрицательных math.floor(-1.3) = -2, тогда дробная часть становится положительной: 0.7.
import math
print(3.14 - math.floor(3.14)) # 0.14000000000000012
print(-1.3 - math.floor(-1.3)) # 0.7Цель: альтернативный способ получения положительной дробной части без оператора %.
Типичные ошибки и их решения
Ошибка 1: Забыли импортировать math
# math.modf(3.14) # NameError: name 'math' is not definedРешение: добавьте import math.
Ошибка 2: Неправильная обработка отрицательных чисел
Новички часто ожидают, что дробная часть всегда положительна. Если используется вычитание целой части, для отрицательных чисел результат отрицательный. Выбирайте метод в зависимости от потребностей.
Ошибка 3: Сравнение дробных частей, полученных разными методами
Из-за погрешности 0.1 + 0.2 != 0.3. Для сравнения используйте math.isclose() или округление.
Расширенные примеры работы с дробной частью
1. Получение дробной части для массива чисел с numpy
import numpy as np
arr = np.array([1.25, -2.5, 3.75])
frac, whole = np.modf(arr)
print("Дробные части:", frac)
print("Целые части:", whole)Дробные части: [ 0.25 -0.5 0.75] Целые части: [ 1. -2. 3.]
Метод np.modf работает поэлементно и поддерживает отрицательные числа, возвращая дробную часть с тем же знаком.
2. Использование pandas для дробной части столбца
import pandas as pd
df = pd.DataFrame({'values': [3.14, -1.7, 0.0, 2.718]})
df['frac'] = df['values'] % 1
print(df)values frac 0 3.140 0.140000 1 -1.700 0.300000 2 0.000 0.000000 3 2.718 0.718000
Обратите внимание: для отрицательных чисел дробная часть положительна (0.3).
3. Получение дробной части с помощью Decimal для гарантированной точности
from decimal import Decimal, getcontext
getcontext().prec = 50 # 50 знаков
numbers = ['0.1', '0.2', '0.3', '1.23456789012345678901234567890']
for s in numbers:
d = Decimal(s)
frac = d % 1
print(f'{s:>30} -> {frac}') 0.1 -> 0.1
0.2 -> 0.2
0.3 -> 0.3
1.23456789012345678901234567890 -> 0.23456789012345678901234567890Дробная часть восстанавливается точно, без погрешности двоичного представления.
4. Обработка NaN, Inf и очень больших чисел
import math
cases = [float('nan'), float('inf'), float('-inf'), 1e308]
for x in cases:
if math.isfinite(x):
frac, whole = math.modf(x)
print(f"{x:15} -> дробная: {frac}, целая: {whole}")
else:
print(f"{x:15} -> не конечное число") nan -> не конечное число
inf -> не конечное число
-inf -> не конечное число
1e+308 -> дробная: 0.0, целая: 1e+308Для конечных чисел math.modf корректно обрабатывает и очень большие значения (дробная часть нулевая).
5. Извлечение дробной части из строкового представления без потери точности
s = "123.45678901234567890"
# Разделение по точке
if '.' in s:
whole, frac = s.split('.')
frac = '0.' + frac
print(f"Целая: {whole}, Дробная: {frac}")
else:
print("Нет дробной части")Целая: 123, Дробная: 0.45678901234567890
Этот метод полезен, когда важна строковая точность (например, для вывода).
6. Сравнение производительности методов (timeit)
import timeit
import math
setup = "import math; x = 3.141592653589793"
methods = [
"math.modf(x)",
"x % 1",
"x - int(x)",
"x - math.floor(x)",
]
for m in methods:
t = timeit.timeit(m, setup, number=1000000)
print(f"{m:20} : {t:.4f} сек")math.modf(x) : 0.4210 сек x % 1 : 0.3892 сек x - int(x) : 0.4187 сек x - math.floor(x) : 0.4271 сек
Все методы сопоставимы по скорости, x % 1 чуть быстрее (для положительных чисел).
7. Дробная часть с использованием fractions.Fraction
from fractions import Fraction
frac = Fraction(3, 2) # 1.5
print(frac.numerator % frac.denominator / frac.denominator) # 0.5Для рациональных чисел дробная часть вычисляется через остаток от деления числителя на знаменатель. Это даёт точный результат без округления.