如何将 pythons Decimal() 类型转换为 INT 和指数

Posted

技术标签:

【中文标题】如何将 pythons Decimal() 类型转换为 INT 和指数【英文标题】:How to Convert pythons Decimal() type into an INT and exponent 【发布时间】:2014-09-16 16:00:09 【问题描述】:

我想在 python 中使用 Decimal() 数据类型并将其转换为整数和指数,以便我可以将该数据发送到具有全精度和小数控制的微控制器/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

对于那些没有编程 PLC 的人,我的替代方法是使用 int 并在两个系统中声明小数点或使用浮点(只有某些 PLC 支持)并且是有损的。所以你可以看到为什么能够做到这一点会很棒!

提前致谢!

【问题讨论】:

太棒了!多谢你们!我采取了rvraghav93的绩效代码,并添加了这里回复的每个人是代码(paste.ubuntu.com/7856669),这里是崩溃:rvraghav93:1.11100006104 ericnutsch:4.22099995613 Smisseim:4.70300006866 Mark_ransom:7.80999994278 ehsan_abd:10.651999504 span 【参考方案1】:
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

【讨论】:

谢谢,这正是我要找的【参考方案2】:
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)

【讨论】:

【参考方案3】:

你可以这样做:

[这比其他方法快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

【讨论】:

您设法绕过了 as_tuple() 函数并大幅提高了性能!也感谢基准测试! 仅供参考:在 python3.5 中仍然适用 @ericnutsch 我永远不会使用time.time 进行代码计时,它没有足够的精度。使用timeit.timeit,我得到 0.31839284114539623 的 to_int_exp 和 1.5341496635228395 的 to_int_exp1。我不知道为什么我的结果如此不同,可能是因为它是 Python 3.8.6。 @MarkRansom,很高兴知道这两个方面。谢谢!【参考方案4】:

直接从元组中获取指数:

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

【讨论】:

以上是关于如何将 pythons Decimal() 类型转换为 INT 和指数的主要内容,如果未能解决你的问题,请参考以下文章

IQueryable<decimal> 转十进制

MySQL的float和decimal的区别疑问

SQL里,如何将数据类型nvarchar转换成float?

c# decimal类型 有没有像string.Empty那样的值?

c#如何将null值附值decimal类型变量

Python decimal.Decimal 以科学计数法产生结果