在Python中查找十进制数小数部分的位数

5
在Python中给定一个Decimal数字,如何找到小数点后的位数?
assert digits(Decimal('1.2345')) == 4
assert digits(Decimal('1000'))   == 0
assert digits(Decimal('1.00'))   == 2
assert digits(Decimal('1E+5'))   == 0
assert digits(Decimal('1.2E+5')) == 0

1
如果小数点后有无限位数字,例如0.3333...会怎么样? - Jiaming Lu
1
我不确定使用 Decimal 类能否实现无限小数位。 - BlackVegetable
Decimal(1) / 3 == Decimal('0.3333333333333333333333333333')。这里会有很多位小数,但这并不代表什么。 - Jiaming Lu
1
我以为精度限制会强制执行,这不是真的吗? - BlackVegetable
Decimal 的默认精度为 28 位数字。用户可以更改,但它不是无限的。 - gerdemb
显示剩余4条评论
2个回答

4

经过一些试验,这个似乎可以正确工作:

def digits(n):
    return max(0,-n.as_tuple().exponent)

NaN+Infinity-Infinity、次标准小数怎么处理? - jfs
NaN+Infinity-Infinity和其他特殊值会引发异常。这不是设计上的问题,但在这些情况下分数位数是未定义的,因此这种行为是合理的。 - gerdemb
subnormal value has an integer exponent。看起来你的方法对于次正常值是有效的。为了与decimal模块保持一致,根据后续使用结果的方式,你可以在出现TypeError(例如NaN等)时返回零。顺便说一下,这应该是被接受的答案(左边的勾号)。 - jfs

2

我将概述一个可能的算法,假设您从一个字符串开始。

  • 从左边开始找到小数点。计算它和 'E' 或字符串末尾之间的数字个数。如果没有小数点,则计数为零。
  • 解析出跟在 'E' 后面的值并转换为整数。如果没有 'E',则为零。
  • 将上述两个值中较大的一个减去另一个;结果是这两个值的最大值和零。所以,'2E-2' 将有两个小数位,'1.2E+5' 将没有小数位,而相当傻的 '0.02E2' 也将没有小数位。
  • 作为极端情况,零本身可能会有零个小数位。至于无穷大和其他特殊值,我没有强烈的意见,它们是否具有零小数位。

似乎这样做可以,但感觉很“hacky”。而且,我开始使用的是Decimal而不是字符串,因此我需要将其转换为字符串才能计算数字。 - gerdemb
一个合理的观点。我不是Decimal API的专家,但我的担忧是,您对对象本身进行的任何评估都可能与仅将其转换为字符串然后计算数字一样费时...并且前期成本更高。 - wberry
此外,我认为这个算法不适用于“1.2E+5”。我们会得到5-1=4,还是我有什么误解? - gerdemb
1
你搞反了,应该是1-5=-4。你需要在算法中再添加一步:如果答案为负数,则返回0。 - morningstar
@morningstar 谢谢,已修复最后一步。 - wberry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接