1

I've got the user entering values such as 10.5 or 9 which, when displayed, result in 10.5 and 9.0 respectively. Instead, I want to trim them down to the non-zero significant figures so that they display as 10.5 and 9.

Is there any way in the standard library to do this easily or should I write my own function? For what it's worth, this is being done in a Django project.

John Debs
  • 3,714
  • 2
  • 25
  • 35

2 Answers2

3
>>> import decimal
>>> d = decimal.Decimal("9.0")
>>> d
Decimal('9.0')
>>> help(d.normalize)
Help on method normalize in module decimal:

normalize(self, context=None) method of decimal.Decimal instance
    Normalize- strip trailing 0s, change anything equal to 0 to 0e0

>>> d.normalize()
Decimal('9')
>>> str(d)
'9.0'
>>> str(d.normalize())
'9'

Although it's possible that by "Decimal" you don't mean decimal.Decimal. In that case, say "float" instead ;-)

EDIT: caution

By "trailing 0s", the docs mean all trailing zeroes, not necessarily just those "after the decimal point". For example,

>>> d = decimal.Decimal("100.000")
>>> d
Decimal('100.000')
>>> d.normalize()
Decimal('1E+2')

If that's not what you want, then I think you'll have to write your own function :-(

EDIT: trying a regexp

The normalize() function here gets a lot closer to what I guess you want:

import re
trailing0 = re.compile(r"""(\.       # decimal point
                            \d*?)    # and as few digits as possible
                           0+$       # before at least 1 trailing 0
                        """, re.VERBOSE)
def replacer(m):
    g = m.group(1)
    if len(g) == 1:
        assert g == "."
        return ""
    else:
        return g

def normalize(x):
    return trailing0.sub(replacer, str(x))

Then, e.g.,

from decimal import Decimal as D
for x in 1.0, 2, 10.010, D("1000.0000"), D("10.5"), D("9.0"):
    print str(x), "->", normalize(x)

displays:

1.0 -> 1
2 -> 2
10.01 -> 10.01
1000.0000 -> 1000
10.5 -> 10.5
9.0 -> 9
Tim Peters
  • 67,464
  • 13
  • 126
  • 132
  • I did mean `decimal.Decimal`. This is exactly what I was looking for – thanks! – John Debs Jan 03 '14 at 21:45
  • Just noticed this myself while testing :(. The answer to the question that Cyber linked to in his comment has the same issue. – John Debs Jan 03 '14 at 22:26
  • Awesome, your regex version does exactly what I asked for. I've posted my own solution as an answer that isn't as robust but is simpler and serves my purpose. I'm marking this as accepted, though, since it answers the original question the best. – John Debs Jan 03 '14 at 22:47
1

Both .normalize() and Python's string formatting options mess up by displaying the value in scientific notation when the zeroes are to the left of the decimal point as well as to the right.

I ended up writing this simple function to do the conversion, which does what I need:

def trim_decimal(d):
    """
    Trims decimal values if they are all 0; otherwise does nothing.
    """
    i = int(d)
    if i == d:
        return i
    return d
John Debs
  • 3,714
  • 2
  • 25
  • 35