从十进制中删除尾随零

b10*_*ard 37 python decimal

我有一个很长的小数列表,我必须根据某些条件调整因子10,100,1000,..... 1000000.当我乘以它们时,有时候我想摆脱无用的尾随零(虽然并不总是).例如...

from decimal import Decimal

# outputs 25.0,  PROBLEM!  I would like it to output 25
print Decimal('2.5') * 10

# outputs 2567.8000, PROBLEM!  I would like it to output 2567.8
print Decimal('2.5678') * 1000
Run Code Online (Sandbox Code Playgroud)

是否有一个函数告诉小数对象丢弃这些无关紧要的零?我能想到这样做的唯一方法是转换为字符串并使用正则表达式替换它们.

应该提一下我使用的是python 2.6.5

编辑发送者的好答案让我意识到我偶尔会得到一个像250.0这样的数字,当标准化时产生2.5E + 2.我想在这些情况下我可以尝试将它们排序并转换为int

sen*_*rle 88

您可以使用该normalize方法删除额外的精度.

>>> print decimal.Decimal('5.500')
5.500
>>> print decimal.Decimal('5.500').normalize()
5.5
Run Code Online (Sandbox Code Playgroud)

为避免在小数点左侧剥离零,可以执行以下操作:

def normalize_fraction(d):
    normalized = d.normalize()
    sign, digits, exponent = normalized.as_tuple()
    if exponent > 0:
        return decimal.Decimal((sign, digits + (0,) * exponent, 0))
    else:
        return normalized
Run Code Online (Sandbox Code Playgroud)

或者更紧凑,使用user7116quantize建议:

def normalize_fraction(d):
    normalized = d.normalize()
    sign, digit, exponent = normalized.as_tuple()
    return normalized if exponent <= 0 else normalized.quantize(1)
Run Code Online (Sandbox Code Playgroud)

您也可以使用此处to_integral()所示,但我认为使用as_tuple这种方式更自我记录.

我在几个案例中对这些进行了测试; 如果您发现不起作用,请发表评论.

>>> normalize_fraction(decimal.Decimal('55.5'))
Decimal('55.5')
>>> normalize_fraction(decimal.Decimal('55.500'))
Decimal('55.5')
>>> normalize_fraction(decimal.Decimal('55500'))
Decimal('55500')
>>> normalize_fraction(decimal.Decimal('555E2'))
Decimal('55500')
Run Code Online (Sandbox Code Playgroud)

  • 哦,那行得通。但我注意到在 250.0 之类的东西上,这会将它转换为 2.5e+02,而不是 250。我意识到我没有在我的 OP 中说这个。有没有办法解决这个问题。 (2认同)

Rod*_*yde 38

这可能是一种更好的方法,但您可以使用它.rstrip('0').rstrip('.')来实现您想要的结果.

以您的数字为例:

>>> s = str(Decimal('2.5') * 10)
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
25
>>> s = str(Decimal('2.5678') * 1000)
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
2567.8
Run Code Online (Sandbox Code Playgroud)

这是针对gerrit在评论中指出的问题的解决方案:

>>> s = str(Decimal('1500'))
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
1500
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于 Decimal('2.5E10')。它会返回2.5E1,这显然是错误的。 (4认同)
  • 这应该包含条件"if".在s`中,否则它会将"1500"改为"15". (3认同)
  • _"如果你把它们转换成字符串"_ - OP _has_在某个时候转换为字符串,因为他输出的是文本! (2认同)

A-I*_*-IV 27

答案来自http://docs.python.org/2/library/decimal.html#decimal-faq

>>> def remove_exponent(d):
...    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

>>> remove_exponent(Decimal('5.500'))
Decimal('5.5')

>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案,因为它直接来自文档. (8认同)
  • 请注意,如果整数十进制数大于上下文精度的位数,则此操作将失败。例如,`remove_exponent(Decimal('5e28'))`将引发`decimal.InvalidOperation:量化结果对于当前上下文有太多数字,尽管默认上下文完全可以表示5e28。 (2认同)

Art*_*kiy 13

答案在FAQ(https://docs.python.org/2/library/decimal.html#decimal-faq)中提到,但没有解释.

要删除小数部分的尾随零,您应该使用normalize:

>>> Decimal('100.2000').normalize()
Decimal('100.2')
>> Decimal('0.2000').normalize()
Decimal('0.2')
Run Code Online (Sandbox Code Playgroud)

但是对于尖锐部分中带有前导零的数字,这种方法有所不同:

>>> Decimal('100.0000').normalize()
Decimal('1E+2')
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们应该使用`to_integral':

>>> Decimal('100.000').to_integral()
Decimal('100')
Run Code Online (Sandbox Code Playgroud)

所以我们可以检查是否有一小部分:

>>> Decimal('100.2000') == Decimal('100.2000').to_integral()
False
>>> Decimal('100.0000') == Decimal('100.0000').to_integral()
True
Run Code Online (Sandbox Code Playgroud)

然后使用适当的方法:

def remove_exponent(num):
    return num.to_integral() if num == num.to_integral() else num.normalize()
Run Code Online (Sandbox Code Playgroud)

试试吧:

>>> remove_exponent(Decimal('100.2000'))
Decimal('100.2')
>>> remove_exponent(Decimal('100.0000'))
Decimal('100')
>>> remove_exponent(Decimal('0.2000'))
Decimal('0.2')
Run Code Online (Sandbox Code Playgroud)

现在我们完成了.


小智 7

使用格式说明符%g.似乎删除尾随零.

>>> "%g" % (Decimal('2.5') * 10)
'25'
>>> "%g" % (Decimal('2.5678') * 1000)
'2567.8'
Run Code Online (Sandbox Code Playgroud)

它也没有Decimal功能

>>> "%g" % (2.5 * 10)
'25'
>>> "%g" % (2.5678 * 1000)
'2567.8'
Run Code Online (Sandbox Code Playgroud)