This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: PEP 3101 string formatting missing engineering presentation type for floating point
Type: enhancement Stage: resolved
Components: Versions: Python 3.6
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: Keith.Brafford, eric.smith, ezio.melotti, hardkrash, mark.dickinson, ncoghlan, r.david.murray, serge.stroobandt, terry.reedy
Priority: normal Keywords:

Created on 2010-03-04 20:12 by hardkrash, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
efloat.py Keith.Brafford, 2010-04-27 19:50 EFLoat class for prototyping engineering notation. also lets you use EFloats from interractive python (i.e. EFloat() + float doesn't turn back into a float)
Messages (11)
msg100413 - (view) Author: steven Michalske (hardkrash) Date: 2010-03-04 20:12
I started using the .format() on strings and was surprised that it was lacking an built in format specifier for engineering notation.

For those unfamiliar with engineering notation it puts the exponent of the number in modulo 3 so that it is in alignment with SI prefixes  such as kilo, micro, milli, etc...

11,000 in engineering notation would be 11.000e3

At this time if i want engineering notation I need to use a function to convert it to a string and then print the string.  Most inconvenient for a standard formatting used in the engineering fields.
msg100415 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-03-04 20:24
This would be a new feature, so it can't be added to 2.6 or 3.2. It's an interesting idea, though.
msg100416 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-03-04 20:31
Not likely to make 2.7, either, unless someone comes forward with a patch real quick.
msg100417 - (view) Author: steven Michalske (hardkrash) Date: 2010-03-04 20:35
Please define real quick.
msg100419 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2010-03-04 20:41
Before 2010-04-03, see http://www.python.org/dev/peps/pep-0373/.

New features can be added only in alpha versions.
msg100461 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2010-03-05 10:06
Before a patch, there needs to be a concrete proposal:  how would this be specified, and what would the precise semantics be?
msg104336 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2010-04-27 16:46
Too late for 2.7, but I would like this to hit 3.2. Some calculators have engineering format as an output option and it would be good for Python.

This issue is being discussed in python-list in thread "Engineering numerical format...". The OP (or someone) posted an Engineer(float) class with a .format method that does what *he* would like. Participants have been invited by Mark to comment here.

It was noted that Decimal has a .to-engineering-string method, but it follows the standard at page 20 of
speleotrove.com/decimal/decarith.pdf
which is different from what is being asked for.
msg104342 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2010-04-27 18:03
After the all-important issue of what letter to use (the folks on the python-list thread suggested 'm', and it seems as good a letter as any, so I'll use it in the examples below), there are some open questions:

(1) The exact form of the output needs to be determined.  For a nonzero finite number, I'm guessing the output should look something like:

'<sign><digits>.<digits>e<exponent>

with at least 1 and at most 3 digits to the left of the point (and the first of those digits being nonzero).  Is this about right?  The sign would be controlled in the same way as for 'e', 'f' and 'g' formatting.  Would the exponent be included even when it's zero, or should it be omitted in that case?

(We'd need to determine how to output zeros, nans and infinities, too, but that shouldn't be a big issue.)

(2) When doing something like 'format(x, '.5m')', what would the 5 refer to?  The two options I see are (a) number of significant digits, or (b) number of digits to the right of the point.  The former seems to make more sense mathematically, but might be a bit awkward when it comes to aligning results in a table:

format(3.2, '.5m')  -> 3.20000e+00
format(13.2, '.5m') -> 13.2000e+00

The latter results in different numbers of significant digits depending on where the exponent lies.

Hmm.  Perhaps there's also (c):  number of places to the right of the *true* decimal point, so that 'm' is more analogous to 'f' than to 'e'.

(3) What should the default precision be?  6 is what's used for 'e', 'f' and 'g' formatting, so should probably also be used for 'm'.

(4) When (if ever) should trailing zeros and a trailing decimal point be omitted (like 'g' formatting does).  I'd say never.

(5) What should the decimal module do?  Call to_eng_string, or try to match float's behaviour?  Formatting for the decimal type has the added complication of trying to preserve significant zeros where possible;  this might require some thought.
msg104350 - (view) Author: Keith Brafford (Keith.Brafford) Date: 2010-04-27 19:50
Ok, let's zero in on how this should work.  I'll start the concrete proposal discussion in terms of how it would have worked with the old-style specifiers (since I am more familiar with that method) and we can bring it up to Py3K standards as a group.

I was thinking something along these lines:
%[<space> | 0 ][.precision]m

where the optional space or zero means that you want the whole number part of the output to be padded to three digits, either with spaces or prepended zeroes.  No space or zero means no prepending of anything.

The .precision would be the number of digits after the decimal point you want to see.  If you don't specify this, then the default would be something that people agreed made the most sense, say 4 for now.

f = math.pi * 1e-5
print f
3.1415926535897935e-005
print "%m" % f
31.4159e-06
print "% m" % f
  31.4159e-06
print "%0m" % f
031.4159e-06
print "% m.6" % f
  31.415927e-06

Mark brought up this point:

e.g. format(12345.678, '.5m'):  Should the '5' indicate 5 digits
after the point (giving '12.34568e+3' in this case), or 5 significant
digits in total (giving '12.345e+3').  

I tend to think that it's more important that the precision number tell you the number of digits after the decimal point.  This is because the underlying float still has all of the precision, and the format specifier is used simply to make the printout look correct.  Being able to specify that you want three slots before the point, then a constant number after the point lets you get perfectly aligned columns in a tabular printout without a lot of fuss.

I wrote a class that I've been using to test these formats out with (attached).  I use it like this:

>>> from efloat impot EFloat as E

it has a class "precision" value that you can set:

>>> E.precision = 5
>>> E(math.pi)
3.14159e+0
>>> E(math.pi / 1e-9)
3.14159e+9
>>> E(math.pi / 1e-2)
314.15927e+0
>>> E(math.pi / 1e-5)
314.15927e+3

It has a slight bug, though.  It doesn't give me two digits of exponent, which would be required in the engineering format specifier, IMHO, so that programmers can easily get constant tabular column widths.
msg216163 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2014-04-14 18:35
After discussing this with Mark at the sprints, I'm going to close this.

If someone comes up with a concrete proposal on python-ideas, we can revisit it. But as it is, there's not enough here to go on.

There are a sufficient number of ideas and alternatives that it might warrant a PEP to record all of the decisions and tradeoffs.
msg259794 - (view) Author: Serge Stroobandt (serge.stroobandt) Date: 2016-02-07 17:24
As per https://bugs.python.org/issue26223#msg259772 , can we please reopen this?

I kind of hate it when *real* issues are kept closed for years (6!) until another lost soul comes by with the same itch...
History
Date User Action Args
2022-04-11 14:56:58adminsetgithub: 52308
2016-02-07 17:24:13serge.stroobandtsetnosy: + serge.stroobandt

messages: + msg259794
versions: + Python 3.6, - Python 3.2
2014-04-14 18:35:45eric.smithsetstatus: open -> closed
resolution: rejected
messages: + msg216163

stage: resolved
2011-10-17 07:36:17ncoghlansetnosy: + ncoghlan
2010-04-27 19:50:19Keith.Braffordsetfiles: + efloat.py
nosy: + Keith.Brafford
messages: + msg104350

2010-04-27 18:04:00mark.dickinsonsetmessages: + msg104342
2010-04-27 16:46:39terry.reedysetnosy: + terry.reedy

messages: + msg104336
versions: - Python 2.7
2010-03-05 10:06:43mark.dickinsonsetmessages: + msg100461
2010-03-04 20:41:53ezio.melottisetmessages: + msg100419
2010-03-04 20:35:15hardkrashsetmessages: + msg100417
2010-03-04 20:31:36r.david.murraysetnosy: + r.david.murray
messages: + msg100416
2010-03-04 20:30:54r.david.murraysetversions: - Python 2.6, Python 3.1
2010-03-04 20:24:19eric.smithsetassignee: eric.smith

messages: + msg100415
nosy: + mark.dickinson
2010-03-04 20:15:08ezio.melottisetpriority: normal
nosy: + eric.smith, ezio.melotti

versions: - Python 3.3
2010-03-04 20:12:47hardkrashcreate