Как преобразовать тип Pythons Decimal() в INT и экспоненту

Я хотел бы использовать тип данных Decimal() в python и преобразовать его в целое число и показатель, чтобы я мог отправлять эти данные в микроконтроллер/plc с полной точностью и десятичным управлением. https://docs.python.org/2/library/decimal.html

У меня есть это работать, но это хакерский; кто-нибудь знает лучший способ? Если нет, то какой путь я бы взял, чтобы написать функцию более низкого уровня "as_int ()"?

пример кода:

from decimal import *
d=Decimal('3.14159')
t=d.as_tuple()
if t[0] == 0:
    sign=1
else:
    sign=-1

digits= t[1]
theExponent=t[2]
theInteger=sign * int(''.join(map(str,digits)))

theExponent
theInteger

для те, которые не запрограммировали PLCs, Моя альтернатива этому-использовать int и объявить десятичную точку в обеих системах или использовать плавающую точку (которую поддерживают только некоторые PLCs) и с потерями. Так что вы можете понять, почему будучи в состоянии сделать это было бы здорово!

спасибо заранее!

4 ответов


вы могли бы сделать это :

[ это в 3 раза быстрее, чем другие методы ]

d=Decimal('3.14159')

list_d = str(d).split('.')   
# Converting the decimal to string and splitting it at the decimal point

# If decimal point exists => Negative exponent
# i.e   3.14159 => "3", "14159"
# exponent = -len("14159") = -5
# integer = int("3"+"14159") = 314159

if len(list_d) == 2:
    # Exponent is the negative of length of no of digits after decimal point
    exponent = -len(list_d[1])
    integer = int(list_d[0] + list_d[1])



# If the decimal point does not exist => Positive / Zero exponent
# 3400
# exponent = len("3400") - len("34") = 2
# integer = int("34") = 34

else:
    str_dec = list_d[0].rstrip('0')
    exponent = len(list_d[0]) - len(str_dec)
    integer = int(str_dec)

print integer, exponent

тестирование производительности

def to_int_exp(decimal_instance):

    list_d = str(decimal_instance).split('.')

    if len(list_d) == 2:
        # Negative exponent
        exponent = -len(list_d[1])
        integer = int(list_d[0] + list_d[1])

    else:
        str_dec = list_d[0].rstrip('0')
        # Positive exponent
        exponent = len(list_d[0]) - len(str_dec)
        integer = int(str_dec)

    return integer, exponent

def to_int_exp1(decimal_instance):
    t=decimal_instance.as_tuple()

    if t[0] == 0:
        sign=1
    else:
        sign=-1

    digits= t[1]

    exponent = t[2]

    integer = sign * int(''.join(map(str,digits)))

    return integer, exponent
Вычисление времени, затраченного на 100 000 циклов для обоих методов :
ttaken = time.time()
for i in range(100000):
    d = Decimal(random.uniform(-3, +3))
    to_int_exp(d)    
ttaken = time.time() - ttaken
print ttaken

время, затраченное на способ разбора строк : 1.56606507301

ttaken = time.time()
for i in range(100000):
    d = Decimal(random.uniform(-3, +3))
    to_int_exp1(d)    
ttaken = time.time() - ttaken
print ttaken

время, необходимое для преобразования в кортеж, затем извлеките метод : 4.67159295082


from functools import reduce   # Only in Python 3, omit this in Python 2.x
from decimal import *

d = Decimal('3.14159')
t = d.as_tuple()

theInteger = reduce(lambda rst, x: rst * 10 + x, t.digits)
theExponent = t.exponent

получить показатель прямо из кортежа, как вы были:

exponent = d.as_tuple()[2]

затем умножьте на соответствующую мощность 10:

i = int(d * Decimal('10')**-exponent)

собираем все вместе:

from decimal import Decimal

_ten = Decimal('10')

def int_exponent(d):
    exponent = d.as_tuple()[2]
    int_part = int(d * (_ten ** -exponent))
    return int_part, exponent

from decimal import *
d=Decimal('3.14159')
t=d.as_tuple()
digits=t.digits
theInteger=0
for x in range(len(digits)):
   theInteger=theInteger+digits[x]*10**(len(digits)-x)