How to suppress scientific notation when printing float values?
Question:
Here’s my code:
x = 1.0
y = 100000.0
print x/y
My quotient displays as 1.00000e-05
.
Is there any way to suppress scientific notation and make it display as
0.00001
? I’m going to use the result as a string.
Answers:
'%f' % (x/y)
but you need to manage precision yourself. e.g.,
'%f' % (1/10**8)
will display zeros only.
details are in the docs
Or for Python 3 the equivalent old formatting or the newer style formatting
In addition to SG’s answer, you can also use the Decimal module:
from decimal import Decimal
x = str(Decimal(1) / Decimal(10000))
# x is a string '0.0001'
With newer versions of Python (2.6 and later), you can use ''.format()
to accomplish what @SilentGhost suggested:
'{0:f}'.format(x/y)
If it is a string
then use the built in float
on it to do the conversion for instance:
print( "%.5f" % float("1.43572e-03"))
answer:0.00143572
Using the newer version ''.format
(also remember to specify how many digit after the .
you wish to display, this depends on how small is the floating number). See this example:
>>> a = -7.1855143557448603e-17
>>> '{:f}'.format(a)
'-0.000000'
as shown above, default is 6 digits! This is not helpful for our case example, so instead we could use something like this:
>>> '{:.20f}'.format(a)
'-0.00000000000000007186'
Update
Starting in Python 3.6, this can be simplified with the new formatted string literal, as follows:
>>> f'{a:.20f}'
'-0.00000000000000007186'
This will work for any exponent:
def getExpandedScientificNotation(flt):
str_vals = str(flt).split('e')
coef = float(str_vals[0])
exp = int(str_vals[1])
return_val = ''
if int(exp) > 0:
return_val += str(coef).replace('.', '')
return_val += ''.join(['0' for _ in range(0, abs(exp - len(str(coef).split('.')[1])))])
elif int(exp) < 0:
return_val += '0.'
return_val += ''.join(['0' for _ in range(0, abs(exp) - 1)])
return_val += str(coef).replace('.', '')
return return_val
This is using Captain Cucumber’s answer, but with 2 additions.
1) allowing the function to get non scientific notation numbers and just return them as is (so you can throw a lot of input that some of the numbers are 0.00003123 vs 3.123e-05 and still have function work.
2) added support for negative numbers. (in original function, a negative number would end up like 0.0000-108904 from -1.08904e-05)
def getExpandedScientificNotation(flt):
was_neg = False
if not ("e" in flt):
return flt
if flt.startswith('-'):
flt = flt[1:]
was_neg = True
str_vals = str(flt).split('e')
coef = float(str_vals[0])
exp = int(str_vals[1])
return_val = ''
if int(exp) > 0:
return_val += str(coef).replace('.', '')
return_val += ''.join(['0' for _ in range(0, abs(exp - len(str(coef).split('.')[1])))])
elif int(exp) < 0:
return_val += '0.'
return_val += ''.join(['0' for _ in range(0, abs(exp) - 1)])
return_val += str(coef).replace('.', '')
if was_neg:
return_val='-'+return_val
return return_val
Using 3.6.4, I was having a similar problem that randomly, a number in the output file would be formatted with scientific notation when using this:
fout.write('someFloats: {0:0.8},{1:0.8},{2:0.8}'.format(someFloat[0], someFloat[1], someFloat[2]))
All that I had to do to fix it was to add ‘f’:
fout.write('someFloats: {0:0.8f},{1:0.8f},{2:0.8f}'.format(someFloat[0], someFloat[1], someFloat[2]))
Since this is the top result on Google, I will post here after failing to find a solution for my problem. If you are looking to format the display value of a float object and have it remain a float – not a string, you can use this solution:
Create a new class that modifies the way that float values are displayed.
from builtins import float
class FormattedFloat(float):
def __str__(self):
return "{:.10f}".format(self).rstrip('0')
You can modify the precision yourself by changing the integer values in {:f}
Another option, if you are using pandas and would like to suppress scientific notation for all floats, is to adjust the pandas options.
import pandas as pd
pd.options.display.float_format = '{:.2f}'.format
As of 3.6 (probably works with slightly older 3.x as well), this is my solution:
import locale
locale.setlocale(locale.LC_ALL, '')
def number_format(n, dec_precision=4):
precision = len(str(round(n))) + dec_precision
return format(float(n), f'.{precision}n')
The purpose of the precision
calculation is to ensure we have enough precision to keep out of scientific notation (default precision is still 6).
The dec_precision
argument adds additional precision to use for decimal points. Since this makes use of the n
format, no insignificant zeros will be added (unlike f
formats). n
also will take care of rendering already-round integers without a decimal.
n
does require float
input, thus the cast.
Most of the answers above require you to specify precision. But what if you want to display floats like this, with no unnecessary zeros:
1
0.1
0.01
0.001
0.0001
0.00001
0.000001
0.000000000001
numpy
has an answer: np.format_float_positional
import numpy as np
def format_float(num):
return np.format_float_positional(num, trim='-')
A simpler solution to display a float to an arbitrary number of significant digits. No numpy
or list comprehensions required here:
def sig(num, digits=3):
"Return number formatted for significant digits"
if num == 0:
return 0
negative = '-' if num < 0 else ''
num = abs(float(num))
power = math.log(num, 10)
if num < 1:
step = int(10**(-int(power) + digits) * num)
return negative + '0.' + '0' * -int(power) + str(int(step)).rstrip('0')
elif power < digits - 1:
return negative + ('{0:.' + str(digits) + 'g}').format(num)
else:
return negative + str(int(num))
I’m stripping trailing 0s and displaying full integers in the example: sig(31415.9) = 31415
instead of 31400. Feel free to modify the code if that’s not something you’re into.
Testing:
for power in range(-8,8):
num = math.pi * 10**power
print(str(num).ljust(25), sig(num))
You can use the built-in format
function.
>>> a = -3.42142141234123e-15
>>> format(a, 'f')
'-0.000000'
>>> format(a, '.50f') # Or you can specify precision
'-0.00000000000000342142141234122994048466990874926279'
In case of numpy arrays you can suppress with suppress command as
import numpy as np
np.set_printoptions(suppress=True)
I was having a similar problem that randomly, using my solution:
from decimal import Decimal
Decimal(2/25500)
#output:0.00007843137254901961000728982664753630160703323781490325927734375
Here’s my code:
x = 1.0
y = 100000.0
print x/y
My quotient displays as 1.00000e-05
.
Is there any way to suppress scientific notation and make it display as
0.00001
? I’m going to use the result as a string.
'%f' % (x/y)
but you need to manage precision yourself. e.g.,
'%f' % (1/10**8)
will display zeros only.
details are in the docs
Or for Python 3 the equivalent old formatting or the newer style formatting
In addition to SG’s answer, you can also use the Decimal module:
from decimal import Decimal
x = str(Decimal(1) / Decimal(10000))
# x is a string '0.0001'
With newer versions of Python (2.6 and later), you can use ''.format()
to accomplish what @SilentGhost suggested:
'{0:f}'.format(x/y)
If it is a string
then use the built in float
on it to do the conversion for instance:
print( "%.5f" % float("1.43572e-03"))
answer:0.00143572
Using the newer version ''.format
(also remember to specify how many digit after the .
you wish to display, this depends on how small is the floating number). See this example:
>>> a = -7.1855143557448603e-17
>>> '{:f}'.format(a)
'-0.000000'
as shown above, default is 6 digits! This is not helpful for our case example, so instead we could use something like this:
>>> '{:.20f}'.format(a)
'-0.00000000000000007186'
Update
Starting in Python 3.6, this can be simplified with the new formatted string literal, as follows:
>>> f'{a:.20f}'
'-0.00000000000000007186'
This will work for any exponent:
def getExpandedScientificNotation(flt):
str_vals = str(flt).split('e')
coef = float(str_vals[0])
exp = int(str_vals[1])
return_val = ''
if int(exp) > 0:
return_val += str(coef).replace('.', '')
return_val += ''.join(['0' for _ in range(0, abs(exp - len(str(coef).split('.')[1])))])
elif int(exp) < 0:
return_val += '0.'
return_val += ''.join(['0' for _ in range(0, abs(exp) - 1)])
return_val += str(coef).replace('.', '')
return return_val
This is using Captain Cucumber’s answer, but with 2 additions.
1) allowing the function to get non scientific notation numbers and just return them as is (so you can throw a lot of input that some of the numbers are 0.00003123 vs 3.123e-05 and still have function work.
2) added support for negative numbers. (in original function, a negative number would end up like 0.0000-108904 from -1.08904e-05)
def getExpandedScientificNotation(flt):
was_neg = False
if not ("e" in flt):
return flt
if flt.startswith('-'):
flt = flt[1:]
was_neg = True
str_vals = str(flt).split('e')
coef = float(str_vals[0])
exp = int(str_vals[1])
return_val = ''
if int(exp) > 0:
return_val += str(coef).replace('.', '')
return_val += ''.join(['0' for _ in range(0, abs(exp - len(str(coef).split('.')[1])))])
elif int(exp) < 0:
return_val += '0.'
return_val += ''.join(['0' for _ in range(0, abs(exp) - 1)])
return_val += str(coef).replace('.', '')
if was_neg:
return_val='-'+return_val
return return_val
Using 3.6.4, I was having a similar problem that randomly, a number in the output file would be formatted with scientific notation when using this:
fout.write('someFloats: {0:0.8},{1:0.8},{2:0.8}'.format(someFloat[0], someFloat[1], someFloat[2]))
All that I had to do to fix it was to add ‘f’:
fout.write('someFloats: {0:0.8f},{1:0.8f},{2:0.8f}'.format(someFloat[0], someFloat[1], someFloat[2]))
Since this is the top result on Google, I will post here after failing to find a solution for my problem. If you are looking to format the display value of a float object and have it remain a float – not a string, you can use this solution:
Create a new class that modifies the way that float values are displayed.
from builtins import float
class FormattedFloat(float):
def __str__(self):
return "{:.10f}".format(self).rstrip('0')
You can modify the precision yourself by changing the integer values in {:f}
Another option, if you are using pandas and would like to suppress scientific notation for all floats, is to adjust the pandas options.
import pandas as pd
pd.options.display.float_format = '{:.2f}'.format
As of 3.6 (probably works with slightly older 3.x as well), this is my solution:
import locale
locale.setlocale(locale.LC_ALL, '')
def number_format(n, dec_precision=4):
precision = len(str(round(n))) + dec_precision
return format(float(n), f'.{precision}n')
The purpose of the precision
calculation is to ensure we have enough precision to keep out of scientific notation (default precision is still 6).
The dec_precision
argument adds additional precision to use for decimal points. Since this makes use of the n
format, no insignificant zeros will be added (unlike f
formats). n
also will take care of rendering already-round integers without a decimal.
n
does require float
input, thus the cast.
Most of the answers above require you to specify precision. But what if you want to display floats like this, with no unnecessary zeros:
1
0.1
0.01
0.001
0.0001
0.00001
0.000001
0.000000000001
numpy
has an answer: np.format_float_positional
import numpy as np
def format_float(num):
return np.format_float_positional(num, trim='-')
A simpler solution to display a float to an arbitrary number of significant digits. No numpy
or list comprehensions required here:
def sig(num, digits=3):
"Return number formatted for significant digits"
if num == 0:
return 0
negative = '-' if num < 0 else ''
num = abs(float(num))
power = math.log(num, 10)
if num < 1:
step = int(10**(-int(power) + digits) * num)
return negative + '0.' + '0' * -int(power) + str(int(step)).rstrip('0')
elif power < digits - 1:
return negative + ('{0:.' + str(digits) + 'g}').format(num)
else:
return negative + str(int(num))
I’m stripping trailing 0s and displaying full integers in the example: sig(31415.9) = 31415
instead of 31400. Feel free to modify the code if that’s not something you’re into.
Testing:
for power in range(-8,8):
num = math.pi * 10**power
print(str(num).ljust(25), sig(num))
You can use the built-in format
function.
>>> a = -3.42142141234123e-15
>>> format(a, 'f')
'-0.000000'
>>> format(a, '.50f') # Or you can specify precision
'-0.00000000000000342142141234122994048466990874926279'
In case of numpy arrays you can suppress with suppress command as
import numpy as np
np.set_printoptions(suppress=True)
I was having a similar problem that randomly, using my solution:
from decimal import Decimal
Decimal(2/25500)
#output:0.00007843137254901961000728982664753630160703323781490325927734375