dropping trailing '.0' from floats
Question:
I’m looking for a way to convert numbers to string format, dropping any redundant ‘.0’
The input data is a mix of floats and strings. Desired output:
0 –> ‘0’
0.0 –> ‘0’
0.1 –> ‘0.1’
1.0 –> ‘1’
I’ve come up with the following generator expression, but I wonder if there’s a faster way:
(str(i).rstrip('.0') if i else '0' for i in lst)
The truth check is there to prevent 0 from becoming an empty string.
EDIT: The more or less acceptable solution I have for now is this:
('%d'%i if i == int(i) else '%s'%i for i in lst)
It just seems strange that there is no elegant way to handle this (fairly straightforward) case in python.
Answers:
Using Python’s string formatting (use str.format() with Python 3.0):
from decimal import Decimal
def format_number(i):
return '%g' % (Decimal(str(i)))
def floatstrip(x):
if x == int(x):
return str(int(x))
else:
return str(x)
Be aware, though, that Python represents 0.1 as an imprecise float, on my system 0.10000000000000001 .
from decimal import Decimal
'%g' % (Decimal(str(x)))
rstrip
doesn’t do what you want it to do, it strips any of the characters you give it and not a suffix:
>>> '30000.0'.rstrip('.0')
'3'
Actually, just '%g' % i
will do what you want.
EDIT: as Robert pointed out in his comment this won’t work for large numbers since it uses the default precision of %g which is 6 significant digits.
Since str(i)
uses 12 significant digits, I think this will work:
>>> numbers = [ 0.0, 1.0, 0.1, 123456.7 ]
>>> ['%.12g' % n for n in numbers]
['1', '0', '0.1', '123456.7']
>>> '%g' % 0
'0'
>>> '%g' % 0.0
'0'
>>> '%g' % 0.1
'0.1'
>>> '%g' % 1.0
'1'
Us the 0 prcision and add a period if you want one. EG “%.0f.”
>>> print "%.0f."%1.0
1.
>>>
(str(i)[-2:] == '.0' and str(i)[:-2] or str(i) for i in ...)
If you only care about 1 decimal place of precision (as in your examples), you can just do:
("%.1f" % i).replace(".0", "")
This will convert the number to a string with 1 decimal place and then remove it if it is a zero:
>>> ("%.1f" % 0).replace(".0", "")
'0'
>>> ("%.1f" % 0.0).replace(".0", "")
'0'
>>> ("%.1f" % 0.1).replace(".0", "")
'0.1'
>>> ("%.1f" % 1.0).replace(".0", "")
'1'
>>> ("%.1f" % 3000.0).replace(".0", "")
'3000'
>>> ("%.1f" % 1.0000001).replace(".0", "")
'1'
>>> x = '1.0'
>>> int(float(x))
1
>>> x = 1
>>> int(float(x))
1
str(x)[-2:] == '.0' and int(x) or x
See PEP 3101:
'g' - General format. This prints the number as a fixed-point
number, unless the number is too large, in which case
it switches to 'e' exponent notation.
Old style (not preferred):
>>> "%g" % float(10)
'10'
New style:
>>> '{0:g}'.format(float(21))
'21'
New style 3.6+:
>>> f'{float(21):g}'
'21'
To print a float
that has an integer value as an int
:
format = "%d" if f.is_integer() else "%s"
print(format % f)
0.0 -> 0
0.1 -> 0.1
10.0 -> 10
12345678.9 -> 12345678.9
123456789.0 -> 123456789
12345678912345.0 -> 12345678912345
12345678912345.6 -> 1.23456789123e+13
1.000000000001 -> 1.0
So much ugliness out thereā¦
My personal favorite is to convert float
s that don’t require to be a float
(= when they actually are integers) to int
, thus removing the, now useless, trailing 0
(int(i) if i.is_integer() else i for i in lst)
Then you can print them normally.
FWIW, with Jinja2 where var = 10.3
{{ var|round|int }}
will emit integer 10
round(method='floor')
and round(method='ceil')
are also available.
So that were var2 = 10.9
{{ var|round(method='floor')|int }}
will still emit integer 10
Precision can also be controlled using a keyword argument precision=0
of the round
function.
Following code will convert contents of variable no as it is i.e. 45.60
. If you use str
the output will be 45.6
no = 45.60
strNo = "%.2f" %no
I was dealing with a value from a json dictionary (returned by an API). All the above didnt help me so i constructed by own helper function. It truncates all the trailing zeros.
I Hope it helps someone out there
def remove_zeros(num):
nums = list(num)
indexes = (list(reversed(range(len(nums)))))
for i in indexes:
if nums[i] == '0':
del nums[-1]
else:
break
return "".join(nums)
num = "0.000000363000"
print(remove_zeros(num))
prints :
0.000000363
I did this for removing trailing nonsignificant digits past a certain precision.
c = lambda x: float(int(x * 100)/100.)
c(0.1234)
I’m looking for a way to convert numbers to string format, dropping any redundant ‘.0’
The input data is a mix of floats and strings. Desired output:
0 –> ‘0’
0.0 –> ‘0’
0.1 –> ‘0.1’
1.0 –> ‘1’
I’ve come up with the following generator expression, but I wonder if there’s a faster way:
(str(i).rstrip('.0') if i else '0' for i in lst)
The truth check is there to prevent 0 from becoming an empty string.
EDIT: The more or less acceptable solution I have for now is this:
('%d'%i if i == int(i) else '%s'%i for i in lst)
It just seems strange that there is no elegant way to handle this (fairly straightforward) case in python.
Using Python’s string formatting (use str.format() with Python 3.0):
from decimal import Decimal
def format_number(i):
return '%g' % (Decimal(str(i)))
def floatstrip(x):
if x == int(x):
return str(int(x))
else:
return str(x)
Be aware, though, that Python represents 0.1 as an imprecise float, on my system 0.10000000000000001 .
from decimal import Decimal
'%g' % (Decimal(str(x)))
rstrip
doesn’t do what you want it to do, it strips any of the characters you give it and not a suffix:
>>> '30000.0'.rstrip('.0')
'3'
Actually, just '%g' % i
will do what you want.
EDIT: as Robert pointed out in his comment this won’t work for large numbers since it uses the default precision of %g which is 6 significant digits.
Since str(i)
uses 12 significant digits, I think this will work:
>>> numbers = [ 0.0, 1.0, 0.1, 123456.7 ]
>>> ['%.12g' % n for n in numbers]
['1', '0', '0.1', '123456.7']
>>> '%g' % 0
'0'
>>> '%g' % 0.0
'0'
>>> '%g' % 0.1
'0.1'
>>> '%g' % 1.0
'1'
Us the 0 prcision and add a period if you want one. EG “%.0f.”
>>> print "%.0f."%1.0
1.
>>>
(str(i)[-2:] == '.0' and str(i)[:-2] or str(i) for i in ...)
If you only care about 1 decimal place of precision (as in your examples), you can just do:
("%.1f" % i).replace(".0", "")
This will convert the number to a string with 1 decimal place and then remove it if it is a zero:
>>> ("%.1f" % 0).replace(".0", "")
'0'
>>> ("%.1f" % 0.0).replace(".0", "")
'0'
>>> ("%.1f" % 0.1).replace(".0", "")
'0.1'
>>> ("%.1f" % 1.0).replace(".0", "")
'1'
>>> ("%.1f" % 3000.0).replace(".0", "")
'3000'
>>> ("%.1f" % 1.0000001).replace(".0", "")
'1'
>>> x = '1.0'
>>> int(float(x))
1
>>> x = 1
>>> int(float(x))
1
str(x)[-2:] == '.0' and int(x) or x
See PEP 3101:
'g' - General format. This prints the number as a fixed-point number, unless the number is too large, in which case it switches to 'e' exponent notation.
Old style (not preferred):
>>> "%g" % float(10)
'10'
New style:
>>> '{0:g}'.format(float(21))
'21'
New style 3.6+:
>>> f'{float(21):g}'
'21'
To print a float
that has an integer value as an int
:
format = "%d" if f.is_integer() else "%s"
print(format % f)
0.0 -> 0
0.1 -> 0.1
10.0 -> 10
12345678.9 -> 12345678.9
123456789.0 -> 123456789
12345678912345.0 -> 12345678912345
12345678912345.6 -> 1.23456789123e+13
1.000000000001 -> 1.0
So much ugliness out thereā¦
My personal favorite is to convert float
s that don’t require to be a float
(= when they actually are integers) to int
, thus removing the, now useless, trailing 0
(int(i) if i.is_integer() else i for i in lst)
Then you can print them normally.
FWIW, with Jinja2 where var = 10.3
{{ var|round|int }}
will emit integer 10
round(method='floor')
and round(method='ceil')
are also available.
So that were var2 = 10.9
{{ var|round(method='floor')|int }}
will still emit integer 10
Precision can also be controlled using a keyword argument precision=0
of the round
function.
Following code will convert contents of variable no as it is i.e. 45.60
. If you use str
the output will be 45.6
no = 45.60
strNo = "%.2f" %no
I was dealing with a value from a json dictionary (returned by an API). All the above didnt help me so i constructed by own helper function. It truncates all the trailing zeros.
I Hope it helps someone out there
def remove_zeros(num):
nums = list(num)
indexes = (list(reversed(range(len(nums)))))
for i in indexes:
if nums[i] == '0':
del nums[-1]
else:
break
return "".join(nums)
num = "0.000000363000"
print(remove_zeros(num))
prints :
0.000000363
I did this for removing trailing nonsignificant digits past a certain precision.
c = lambda x: float(int(x * 100)/100.)
c(0.1234)