Дробная часть 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

Для рациональных чисел дробная часть вычисляется через остаток от деления числителя на знаменатель. Это даёт точный результат без округления.

Дробная часть числа float в Python - comments

En
Python дробная часть float (python)