5

How would I do the following:

>>> num_decimal_places('3.2220')
3 # exclude zero-padding

>>> num_decimal_places('3.1')
1

>>> num_decimal_places('4')
0

I was thinking of doing:

len((str(number) if '.' in str(number) else str(number) + '.').rstrip('0').split('.')[-1])

Is there another, simpler way to do this?

David542
  • 101,766
  • 154
  • 423
  • 727

7 Answers7

4

You can use a regex to parse value, capture the decimal digits and count the length of the match, if any:

import re

def num_decimal_places(value):
    m = re.match(r"^[0-9]*\.([1-9]([0-9]*[1-9])?)0*$", value)
    return len(m.group(1)) if m is not None else 0

this is a bit less "raw" than splitting the string with multiple if else, not sure if simpler or more readable, though.

Stefano Sanfilippo
  • 30,653
  • 7
  • 76
  • 79
3

The best and the most Pythonic way to achieve this is:

import decimal
x = '56.001000'
x = x.rstrip('0')  # returns '56.001'
x = decimal.Decimal(x)  # returns Decimal('0.001')
x = x.as_tuple().exponent  # returns -3
x = abs(x)  #returns 3

Above code can be written in simpler way as:

>>> x = '56.001000'
>>> abs(decimal.Decimal(x.rstrip('0')).as_tuple().exponent)
3

Below is the list of used functions for more reference:

  1. str.rstrip(): Return a copy of the string with trailing characters removed.
  2. decimal.Decimal(): Construct a new Decimal object based from value.
  3. x.as_tuple(): Returns a namedtuple of the format: DecimalTuple(sign=0, digits=(1,), exponent=-3)
  4. abs(): Return the absolute value of a number.
Moinuddin Quadri
  • 43,657
  • 11
  • 92
  • 117
  • Thanks, I didnt know about the Decimal lib. I actually think this is more pythonic than the regex solution – 3pitt Nov 19 '20 at 02:47
2

You dont need regex, you can convert to float and convert back to string! this automatically will remove the zeroes :

>>> def convertor(s):
...       try :
...          int(s.rstrip('0').rstrip('.'))
...          return 0
...       except: 
...          return len(str(float(s)).split('.')[-1])
... 
>>> convertor('4.0230')
3
>>> convertor('4.0')
0
>>> convertor('4')
0
Mazdak
  • 100,514
  • 17
  • 155
  • 179
1

you could also just try something like:

try:
    return len(str(num).split('.')[1].rstrip('0'))
except
    return 0
David542
  • 101,766
  • 154
  • 423
  • 727
acushner
  • 8,972
  • 1
  • 32
  • 32
0

By string process:

  1. Check . is present in number string or not.
  2. If Not present then return 0.
  3. If present the split number string by . and get second item from the split result.
  4. Remove 0 from the right side.
  5. Return len of item.

code:

>>> def dCount(no_str):
...    if "." in no_str:
...         return len(no_str.split(".")[1].rstrip("0"))
...    else:
...         return 0
... 
>>> dCount("2")
0
>>> dCount("2.002")
3
>>> dCount("2.1230")
3
>>> dCount("2.01230")
4
>>> 
Vivek Sable
  • 9,246
  • 3
  • 34
  • 50
0
import re

def f(s):
    ls = s.split('.', 1)
    if len(ls) == 2 and re.match(r'\d*$', ls[1]):
        return len(ls[1].rstrip('0'))
    return 0

assert f('12') == 0
assert f('12.') == 0
assert f('12.1') == 1
assert f('12.100006') == 6
assert f('12.1.3') == 0
assert f('12.1abc') == 0
assert f('12.100000') == 1
ferhat
  • 3,615
  • 1
  • 18
  • 25
-1

You could try using the Decimal function in python:

abs(Decimal(string_value).as_tuple().exponent)

as explained in Easy way of finding decimal places

Community
  • 1
  • 1
Pedro Braz
  • 2,121
  • 3
  • 23
  • 44
  • That doesn't quite work if you don't strip the zero-padding: `>>> string_value = '4.2200' >>> abs(Decimal(string_value).as_tuple().exponent) 4 ` – David542 Feb 26 '15 at 17:49
  • Decimal is tricky. For example: `abs(Decimal('12.0003').as_tuple().exponent)` returns `48` – ferhat Feb 26 '15 at 17:53