How to separate decimal value in python

I have come up with two statements that can divide positive and negative numbers into integer and fraction without compromising accuracy (bit overflow) and speed.

As an example, a positive or negative value of the value 100.1323 will be divided as:
100.1323 -> (100, 0.1323)
-100.1323 -> (-100, -0.1323)

Code

# Divide a number (x) into integer and fraction
i = int(x) # Get integer
f = (x*1e17 - i*1e17) / 1e17 # Get fraction

Speedtest

The performance test shows that the two statements are faster than math.modf, as long as they are not put into their own function or method.

test.py:

#!/usr/bin/env python
import math
import cProfile

""" Get the performance of both statements and math.modf """

X = -100.1323  # The number to be divided into integer and fraction
LOOPS = range(5 * 10 ** 6)  # Number of loops


def scenario_a():
    """ Get the performance of the statements """
    for _ in LOOPS:
        i = int(X)  # -100
        f = (X*1e17-i*1e17)/1e17  # -0.1323


def scenario_b():
    """ Tests the speed of the statements when integer need to be float.
        NOTE: The only difference between this and math.modf is the accuracy """
    for _ in LOOPS:
        i = int(X)  # -100
        i, f = float(i), (X*1e17-i*1e17)/1e17  # (-100.0, -0.1323)


def scenario_c():
    """ Tests the speed of the statements in a function """
    def modf(x):
        i = int(x)
        return i, (x*1e17-i*1e17)/1e17

    for _ in LOOPS:
        i, f = modf(X)  # (-100, -0.1323)


def scenario_d():
    """ Tests the speed of math.modf """
    for _ in LOOPS:
        f, i = math.modf(X)  # (-0.13230000000000075, -100.0)


def scenario_e():
    """ Tests the speed of math.modf when the integer part should be integer """
    for _ in LOOPS:
        f, i = math.modf(X)  # (-0.13230000000000075, -100.0)
        i = int(i)  # -100


if __name__ == '__main__':
    cProfile.run('scenario_a()')
    cProfile.run('scenario_b()')
    cProfile.run('scenario_c()')
    cProfile.run('scenario_d()')
    cProfile.run('scenario_e()')

Result:

         4 function calls in 1.357 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.357    1.357 :1()
        1    1.357    1.357    1.357    1.357 test.py:11(scenario_a)
        1    0.000    0.000    1.357    1.357 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         4 function calls in 1.858 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.858    1.858 :1()
        1    1.858    1.858    1.858    1.858 test.py:18(scenario_b)
        1    0.000    0.000    1.858    1.858 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         5000004 function calls in 2.744 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.744    2.744 :1()
        1    1.245    1.245    2.744    2.744 test.py:26(scenario_c)
  5000000    1.499    0.000    1.499    0.000 test.py:29(modf)
        1    0.000    0.000    2.744    2.744 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         5000004 function calls in 1.904 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.904    1.904 :1()
        1    1.073    1.073    1.904    1.904 test.py:37(scenario_d)
        1    0.000    0.000    1.904    1.904 {built-in method builtins.exec}
  5000000    0.831    0.000    0.831    0.000 {built-in method math.modf}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         5000004 function calls in 2.547 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.547    2.547 :1()
        1    1.696    1.696    2.547    2.547 test.py:43(scenario_e)
        1    0.000    0.000    2.547    2.547 {built-in method builtins.exec}
  5000000    0.851    0.000    0.851    0.000 {built-in method math.modf}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Use C/C++ extension

I have tried to compile the two statements with C/C++ support and the result was even better. With Python extension module it was possible to get a method that was faster and more accurate than math.modf.

math2.pyx:

def modf(number):
    cdef float num =  number
    cdef int i =  num
    return i, (num*1e17 - i*1e17) / 1e17

See Basics of Cython

test.py:

#!/usr/bin/env python
import math
import cProfile
import math2

""" Get the performance of both statements and math.modf """

X = -100.1323  # The number to be divided into integers and fractions
LOOPS = range(5 * 10 ** 6)  # Number of loops


def scenario_a():
    """ Tests the speed of the statements in a function using C/C++ support """
    for _ in LOOPS:
        i, f = math2.modf(X)  # (-100, -0.1323)


def scenario_b():
    """ Tests the speed of math.modf """
    for _ in LOOPS:
        f, i = math.modf(X)  # (-0.13230000000000075, -100.0)


if __name__ == '__main__':
    cProfile.run('scenario_a()')
    cProfile.run('scenario_b()')

Result:

         5000004 function calls in 1.629 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.629    1.629 :1()
        1    1.100    1.100    1.629    1.629 test.py:10(scenario_a)
        1    0.000    0.000    1.629    1.629 {built-in method builtins.exec}
  5000000    0.529    0.000    0.529    0.000 {math2.modf}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         5000004 function calls in 1.802 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.802    1.802 :1()
        1    1.010    1.010    1.802    1.802 test.py:16(scenario_b)
        1    0.000    0.000    1.802    1.802 {built-in method builtins.exec}
  5000000    0.791    0.000    0.791    0.000 {built-in method math.modf}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

NOTE

The statements can be faster with modulo, but modulo can not be used to split negative numbers into integer and fraction parts.

i, f = int(x), x*1e17%1e17/1e17 # Divide a number (x) into integer and fraction

As an example, a positive or negative value of the value 100.1323 will be divided as:
100.1323 -> (100, 0.1323)
-100.1323 -> (-100, 0.8677) <-- Wrong

How do you separate decimal places in Python?

Use math..
num = 1.2426..
separated_num = math. modf(num).
print(separated_num).

How do you separate decimal values?

How to separate whole number (integer) from decimal in Excel?.
Select a blank cell such as B2, enter this formula =TRUNC(A2) into it and then press the Enter key..
Select the result cell, and then drag the Fill Handle down to get all whole numbers from specified cells..

How do you get a decimal value in Python?

Python has several ways to round decimal digits:.
The round() function rounds decimal places up and down. This makes 4.458 into 4.46 and 8.82392 into 8.82 ..
To round decimal places up we have to use a custom function. That way 8.343 becomes 8.35 ..
To round decimal places down we use a custom function..

How do you split digits in Python?

To split an integer into digits: Use the str() class to convert the integer to a string. Use a list comprehension to iterate over the string. On each iteration, use the int() class to convert each substring to an integer.