Python math.modf(): Separate Fractional and Integer Parts

The math.modf(x) function separates a real number x into its fractional and integer components, returning both as a 2-element tuple of floats: (fractional_part, integer_part). Crucially, both parts inherit the mathematical sign of x, and the integer component is returned as a float (e.g. 23.0, not 23).

Exact Component Order: Notice that the fractional part comes first (result[0]) and the integer part comes second (result[1]), satisfying the exact relation result[0] + result[1] == x.

Syntax & Parameters 🔝

The math.modf() function belongs to Python's standard math module and wraps the C standard library modf() function directly:

import math

fraction, integer = math.modf(x)
Component Type Description
x float or int Required. The numeric value to split into parts.
fractional_part float The fractional portion of x. Carries the sign of x, with magnitude in [0.0, 1.0).
integer_part float The integral portion of x (truncated towards zero). Carries the sign of x.
Return Value tuple A 2-element tuple of floats: (float, float).
TypeError Exception Raised when passing non-numeric data types (strings, lists, None).

Basic Usage & Tuple Unpacking 🔝

You can inspect the raw returned tuple or unpack it immediately into two separate variables:

import math

# Standard floating-point number
parts = math.modf(23.45)
print("modf(23.45):       ", parts)
print("Fractional (index 0):", parts[0])
print("Integer    (index 1):", parts[1])

# Pure integer inputs return 0.0 fractional part
print("modf(42):          ", math.modf(42))

# Mathematical constants like pi
print("modf(math.pi):     ", math.modf(math.pi))

Output:

modf(23.45):        (0.4499999999999993, 23.0)
Fractional (index 0): 0.4499999999999993
Integer    (index 1): 23.0
modf(42):           (0.0, 42.0)
modf(math.pi):      (0.14159265358979312, 3.0)

Because the return value is a standard Python tuple, the idiomatic way to handle the output is unpacking:

frac, whole = math.modf(123.75)
print(f"Whole dollars: {int(whole)}, Cents portion: {frac:.2f}")

Output:

Whole dollars: 123, Cents portion: 0.75

Sign Inheritance with Negative Numbers 🔝

One of the most important behaviors of math.modf() is that both parts retain the sign of the original input. If the input is negative, both the fractional and integer parts are negative:

import math

frac, whole = math.modf(-12.34)
print("Fractional:", frac)   # Negative float
print("Integer:   ", whole)  # Negative float
print("Sum check: ", frac + whole)

Output:

Fractional: -0.33999999999999986
Integer:    -12.0
Sum check:  -12.34

This behavior preserves the identity frac + whole == x across both positive and negative axes, distinguishing modf() from Python's modulo operator (%) and divmod(), which always return a positive remainder.

IEEE 754 Floating-Point Precision Nuance 🔝

In the examples above, you might notice that math.modf(23.45) returned 0.4499999999999993 instead of exactly 0.45. This is not a bug in Python or math.modf(); it is a fundamental property of the IEEE 754 binary floating-point standard.

Just as the fraction 1/3 cannot be represented in a finite number of decimal digits (0.3333...), the decimal number 0.45 cannot be represented exactly in binary powers of two (base 2). If your application requires exact decimal display without floating-point artifacts, clean the result using round() or string formatting:

import math

frac, whole = math.modf(23.45)
clean_frac = round(frac, 4)

print("Raw fraction:  ", frac)
print("Clean fraction:", clean_frac)

Output:

Raw fraction:   0.4499999999999993
Clean fraction: 0.45

math.modf() vs. int() vs. math.floor() vs. % 1 🔝

Python developers frequently encounter multiple methods for extracting whole and decimal parts. The table below compares their outputs on positive and negative values:

Operation Input: 7.75 Input: -7.75 Handling Rule
math.modf(x) (0.75, 7.0) (-0.75, -7.0) Returns both parts as floats; inherits sign of x.
int(x) 7 -7 Returns pure integer truncated towards zero.
math.trunc(x) 7 -7 Truncates decimals towards zero (returns integer).
math.floor(x) 7 -8 Rounds downwards towards -∞ (returns integer).
x % 1.0 0.75 0.25 Floor modulo; result is always ≥ 0.0.
divmod(x, 1) (7.0, 0.75) (-8.0, 0.25) Uses floor division; remainder is always ≥ 0.0.

Notice that for negative numbers, math.modf(-7.75) gives the intuitive fractional part -0.75, whereas -7.75 % 1 gives 0.25.

Special Values: Zero, Inf, and NaN 🔝

Special IEEE 754 floating-point values are handled predictably:

Input x Output (frac, whole) Description
0.0 (0.0, 0.0) Both components are positive zero.
-0.0 (-0.0, -0.0) Both components preserve IEEE 754 signed negative zero.
float('inf') (0.0, inf) Fractional part is zero; integer part is positive infinity.
float('-inf') (-0.0, -inf) Preserves negative sign on both components.
float('nan') (nan, nan) Both components are Not-a-Number (NaN).
import math

print("modf(0.0):  ", math.modf(0.0))
print("modf(-0.0): ", math.modf(-0.0))
print("modf(inf):  ", math.modf(float('inf')))
print("modf(nan):  ", math.modf(float('nan')))

Output:

modf(0.0):   (0.0, 0.0)
modf(-0.0):  (-0.0, -0.0)
modf(inf):   (0.0, inf)
modf(nan):   (nan, nan)

Hands-on Exercise: GPS Decimal Degrees to DMS Converter with Assertions 🔝

In Geographic Information Systems (GIS) and navigation, latitude and longitude coordinates are often given in Decimal Degrees (DD) (e.g. 37.774929). To display them in human-readable navigation charts, they must be converted into Degrees, Minutes, and Seconds (DMS):

  1. Extract the whole degrees using math.modf().
  2. Multiply the fractional degree by 60 to obtain total minutes.
  3. Call math.modf() on the total minutes to extract whole minutes and fractional minutes.
  4. Multiply the fractional minutes by 60 to obtain seconds.
Python Exercise: Decimal Degrees (DD) to DMS Converter
import math

def dd_to_dms(decimal_degrees, is_latitude=True):
    """
    Converts decimal degrees coordinate to (degrees, minutes, seconds, compass_direction).
    """
    if not isinstance(decimal_degrees, (int, float)):
        raise TypeError("Coordinate must be a numeric value.")
    
    is_negative = decimal_degrees < 0
    abs_dd = abs(decimal_degrees)
    
    # 1. Separate degrees and fractional degree
    frac_deg, deg = math.modf(abs_dd)
    
    # 2. Convert fractional degree to minutes
    total_minutes = frac_deg * 60.0
    frac_min, minutes = math.modf(total_minutes)
    
    # 3. Convert fractional minutes to seconds
    seconds = round(frac_min * 60.0, 2)
    
    # Determine cardinal direction
    if is_latitude:
        direction = "S" if is_negative else "N"
    else:
        direction = "W" if is_negative else "E"
        
    return (int(deg), int(minutes), seconds, direction)

# Unit Assertions
# San Francisco Latitude: 37.7749° N -> 37° 46' 29.64" N
assert dd_to_dms(37.7749, is_latitude=True) == (37, 46, 29.64, 'N')

# San Francisco Longitude: -122.4194° W -> 122° 25' 9.84" W
assert dd_to_dms(-122.4194, is_latitude=False) == (122, 25, 9.84, 'W')

# Prime Meridian / Equator origin check
assert dd_to_dms(0.0) == (0, 0, 0.0, 'N')

# Type verification
try:
    dd_to_dms("37.77")
    assert False, "Should raise TypeError"
except TypeError:
    pass

lat_dms = dd_to_dms(37.7749, True)
lon_dms = dd_to_dms(-122.4194, False)

print(f"San Francisco: {lat_dms[0]}° {lat_dms[1]}' {lat_dms[2]}\" {lat_dms[3]}, {lon_dms[0]}° {lon_dms[1]}' {lon_dms[2]}\" {lon_dms[3]}")
print("All GPS DMS conversion assertions passed successfully!")

Practice in Google Colab & GitHub 🔝

Open in Google Colab View on GitHub

Run all math.modf() examples interactively, test sign inheritance, compare with divmod() and math.floor(), and convert geographic GPS coordinates in Google Colab.




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer