1

What is the best way to convert Decimal to a pair of integers to get whole and fractional in python? By saying best - I mean efficient, exact and using underlaying structure of the data type. e.g.:

d = Decimal('1536310893.687185000')
whole, fractional = some_func(d)
print(whole)
1536310893
print(fractional)
687185000

I believe there is more efficient way than to just split string representation :) I also think that Decimal is stored in memory as a pair of integers, the question is how to get them? :)

regina_fallangi
  • 2,080
  • 2
  • 18
  • 38

4 Answers4

2

Use divmod

>>> divmod(d, 1)
(Decimal('1536310893'), Decimal('0.687185000'))
napuzba
  • 6,033
  • 3
  • 21
  • 32
1

Try this using split:

d = Decimal('1536310893.687185000')
whole, fractional = map(float,str(d).split('.'))
print(whole)
print(fractional)

Output:

1536310893
687185000

Better math.modf:

import math
whole, fractional = math.modf(d)
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
1

If you need it done by using the properties of the Decimal class you can use this function for some_func():

from decimal import *

def whole_and_fractional_part(d):
    getcontext().rounding = ROUND_FLOOR
    return d.to_integral_exact(), d - d.to_integral_exact()

This gives the output:

In [34]: whole, fractional
Out[34]: (Decimal('1536310893'), Decimal('0.687185'))
Vedang Waradpande
  • 660
  • 1
  • 6
  • 8
  • looks promising, I just need to know a number of digits after fixed point (x), and then I can multiply Fractional part by 10^x. I think It could be the most efficient. I ned to measure perforamnce... – Евгений Артеменко Sep 23 '18 at 17:54
1

Decimal can be created with tuple (sign, digits, exponent) where a sign (0 for positive or 1 for negative), a tuple of digits, and an integer exponent. decimal.as_tuple() return this representation. using those options we can write the following:

def whole_frac_int(d):
    sign,digits,exp = d.normalize().as_tuple()
    return ( 
      int( decimal.Decimal( (sign,digits[:exp],0) ) ),
      int( decimal.Decimal( (sign,digits[exp:],0) ) )
    )

>>> whole_frac_int( decimal.Decimal('1536310893.687185000')
(1536310893, 687185)
napuzba
  • 6,033
  • 3
  • 21
  • 32