I want to represent a floating-point number as a string rounded to some number of significant digits, and never using the exponential format. Essentially, I want to display any floating-point number and make sure it “looks nice”.
There are several parts to this problem:
- I need to be able to specify the
number of significant digits. - The number of significant digits
needs to be variable, which can’t be
done with with the string formatting
operator. [edit] I’ve been corrected; the string formatting operator can do this. - I need it to be rounded the way a
person would expect, not something
like 1.999999999999
I’ve figured out one way of doing this, though it looks like a work-round and it’s not quite perfect. (The maximum precision is 15 significant digits.)
>>> def f(number, sigfig):
return ("%.15f" % (round(number, int(-1 * floor(log10(number)) + (sigfig - 1))))).rstrip("0").rstrip(".")
>>> print f(0.1, 1)
0.1
>>> print f(0.0000000000368568, 2)
0.000000000037
>>> print f(756867, 3)
757000
Is there a better way to do this? Why doesn’t Python have a built-in function for this?
It appears there is no built-in string formatting trick which allows you to (1) print floats whose first significant digit appears after the 15th decimal place and (2) not in scientific notation. So that leaves manual string manipulation.
Below I use the
decimalmodule to extract the decimal digits from the float.The
float_to_decimalfunction is used to convert the float to aDecimalobject. The obvious waydecimal.Decimal(str(f))is wrong becausestr(f)can lose significant digits.float_to_decimalwas lifted from the decimal module’s documentation.Once the decimal digits are obtained as a tuple of ints, the code below does the obvious thing: chop off the desired number of sigificant digits, round up if necessary, join the digits together into a string, tack on a sign, place a decimal point and zeros to the left or right as appropriate.
At the bottom you’ll find a few cases I used to test the
ffunction.