Number of digits in exponent
Asked Answered
L

4

27

Is it possible to set the number of digits to be used for printing the exponent of a floating-point number? I want to set it to 3.

Currently,

f = 0.0000870927939438012
>>> "%.14e"%f
'8.70927939438012e-05'
>>> "%0.14e"%f
'8.709279e-005'

What I want to print is: '8.70927939438012e-005'

Leathaleather answered 28/3, 2012 at 15:37 Comment(2)
How come second example has less precision and 3 digits in exponent?Argue
On my machine "%e" % f outputs '8.709279e-05' and "%0.14e" % f outputs '8.70927939438012e-05'. Also, higher precision should be possible with libraries such as mpmath. However, I don’t know if it fits your needs.Allophane
A
23

There is a no way to control that, best way is to write a function for this e.g.

def eformat(f, prec, exp_digits):
    s = "%.*e"%(prec, f)
    mantissa, exp = s.split('e')
    # add 1 to digits as 1 is taken by sign +/-
    return "%se%+0*d"%(mantissa, exp_digits+1, int(exp))

print(eformat(0.0000870927939438012, 14, 3))
print(eformat(1.0000870927939438012e5, 14, 3))
print(eformat(1.1e123, 4, 4))
print(eformat(1.1e-123, 4, 4))

Output:

8.70927939438012e-005
1.00008709279394e+005
1.1000e+0123
1.1000e-0123
Argue answered 28/3, 2012 at 16:22 Comment(4)
Anurag, there are various ways to manipulate this as a string and obtain the three digits in the exponent. What I was interested in is to avoid string manipulation since the second example in my post shows that Python natively uses three digits in some case. Still not sure why it does so, as you have also asked above. I merely found it while experimenting.Leathaleather
@Leathaleather I don't think there are any public function for that, you should try looking into python code to see what it is actually doing, though I don't see 3 digits in exponent on python 2.7Argue
@Anurag: three-digit exponents did appear on some platforms for Python 2.5; this was fixed in Python 2.6 (I believe). See bugs.python.org/issue1600 for more.Phage
I'm sad that this answer is correct, sure would be nice if you could specify the number of digits... almost downvoted...Matter
D
20

You can use np.format_float_scientific

from numpy import format_float_scientific

f = 0.0000870927939438012

format_float_scientific(f, exp_digits=3) # prints '8.70927939438012e-005'

format_float_scientific(f, exp_digits=5, precision=2) #prints '8.71e-00005'
Dexter answered 14/11, 2018 at 11:35 Comment(0)
C
0

Here is a slightly more flexible answer (does either 'e' or 'E' to separate mantissa and exponent, is forgiving of missing/bad arguments). But I am upvoting the answer from @AnuragUniyal because that answer is so compact.

def efmte(x, n=6, m=2, e='e', nmax=16):
    def _expc(s): # return exponent character of e-formatted float
        return next(filter(lambda character: character in {'E', 'e'}, s))
    def _pad0(s, n): # return string padded to length n
        return ('{0:0>' + str(n) + '}').format(s)
    def _efmtes(s, n): # reformat e-formatted float: n e-digits
        m, e, p = s.partition(_expc(s)) # mantissa, exponent, +/-power
        return m + e + p[0] + _pad0(p[1:], n)
    def _efmt(x, n, e): # returns formatted float x: n decimals, 'e'/'E'
        return ('{0:.' + str(n) + e + '}').format(x)
    x = x if isinstance(x, float) else float('nan')
    nmax = 16 if not isinstance(nmax, int) else max(0, nmax)
    n = 6 if not isinstance(n, int) else min(max(0, n), nmax)
    m = 2 if not isinstance(m, int) else max(0, m)
    e = 'e' if e not in {'E', 'e'} else e
    return _efmtes(_efmt(x, n, e), m)

Examples:

>>> efmte(42., n=1, m=5)
'4.2e+00001'
>>> efmte('a')
'-1.#IND00e+00'
>>> # Yuck: I was expecting 'nan'. Anyone else?
>>> from math import pi
>>> efmte(pi)
'3.141593e+00'
>>> efmte(pi, m=3)
'3.141593e+000'
Crowning answered 10/10, 2018 at 1:26 Comment(0)
G
0

Similar to @Anurag Uniyal answer, but optionally removing the sign in the exponent (useful if one is tight in space).

def expformat(f, prec, exp_digits, sign='on'):
    """Scientific-format a number with a given number of digits in the exponent.
    Optionally remove the sign in the exponent"""
    s = "%.*e"%(prec, f)
    mantissa, exp = s.split('e')
    if (sign=='on') :
        # add 1 to digits as 1 is taken by sign +/-
        return "%se%+0*d"%(mantissa, exp_digits+1, int(exp))
    else :
        return "%se%0*d"%(mantissa, exp_digits, int(exp))
Goya answered 22/12, 2019 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.