Reputation: 110093
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?
Upvotes: 6
Views: 3076
Reputation: 61498
Use the partition
method of strings to get the decimal portion - this returns a 3-tuple regardless of whether the string actually contains a decimal point or any digits after it. Then simply remove trailing zeros from the decimal portion and count the remaining digits. Thus:
def needed_precision(number_string):
whole, period, decimal = number_string.partition('.')
return len(decimal.rstrip('0'))
This can of course be inlined:
len(number_string.partition('.')[2].rstrip('0'))
Which is less readable, but quite short and straightforward.
Upvotes: 0
Reputation: 9922
The Decimal
type is perfect for this, you can implement num_decimal_places()
as follows:
from decimal import Decimal
def num_decimal_places(value: str):
return -Decimal(value).normalize().as_tuple().exponent
It works as follows: Decimal(value)
parses the string, including exponent notation, then .normalize()
strips any trailing zeros from the internal representation. .as_tuple().exponent
contains the number of decimal places the internally stored integer is shifted to the left, so negative numbers specify the number of places to the right of the decimal.
Upvotes: 0
Reputation: 48067
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:
Upvotes: 3
Reputation: 107287
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
Upvotes: 2
Reputation: 3978
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
Upvotes: 0
Reputation: 9946
you could also just try something like:
try:
return len(str(num).split('.')[1].rstrip('0'))
except
return 0
Upvotes: 1
Reputation: 10213
By string process:
.
is present in number string or not..
and get second item from the split result.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
>>>
Upvotes: 1
Reputation: 33046
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.
Upvotes: 4
Reputation: 2401
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
Upvotes: -1