From: Keith on 25 Apr 2010 23:36 I am considering writing a PEP for the inclusion of an engineering format specifier, and would appreciate input from others. Background (for those who don't already know about engineering notation): Engineering notation (EN) is type of floating point representation. The idea with EN is that the powers of 10 are all multiples of 3, which correspond to the familiar Greek unit prefixes that engineers use when describing the different sizes of all sorts of real-world devices and phenomena: 1e-12 == pico 1e-9 == nano 1e-6 == micro 1e-3 == milli 1e+3 == kilo 1e+6 == mega 1e+9 == giga When people are talking about Ohms, Farads, Henries, Hz, and many others, they routinely have to normalize to EN. Fancy calculators from HP and TI routinely allow the users to go into engineering mode, but mysteriously things like C, Python, Excel, etc. don't For instance, no one talks about 4.7e-5F, as they would rather see 47e-6 (micro). Instead of 2.2e-2, engineers need to see 22.0e-3 (milli). Originally to address this issue, I wrote for myself an "EFloat" class that subclassed float: import math class EFloat(float): """EFloat(x) -> floating point number with engineering representation when printed Convert a string or a number to a floating point number, if possible. When asked to render itself for printing (via str() or print) it is normalized to engineering style notation at powers of 10 in multiples of 3 (for micro, milli, kilo, mega, giga, etc.) """ def __init__(self, value=0.0, prec=12): super(EFloat, self).__init__(value) self.precision = prec def _get_precision(self): return self._precision def _set_precision(self, p): self._precision = p self.format_string = "%3." + ("%d" % self._precision) + "fe% +d" return precision = property(_get_precision, _set_precision, doc="The number of decimal places printed") def _exponent(self): if self == 0.0: ret = 0 else: ret = math.floor(math.log10(abs(self))) return ret def _mantissa(self): return self/math.pow(10, self._exponent()) def _asEng(self): shift = self._exponent() % 3 retval = self.format_string % (self._mantissa()*math.pow(10, shift), self._exponent() - shift) return retval def __str__(self): return self._asEng() def __repr__(self): return str(self) def __add__(self, x): return EFloat(float.__add__(self, float(x))) def __radd__(self, x): return EFloat(float.__add__(self, float(x))) def __mul__(self, x): return EFloat(float.__mul__(self, float(x))) def __rmul__(self, x): return EFloat(float.__mul__(self, float(x))) def __sub__(self, x): return EFloat(float.__sub__(self, float(x))) def __rsub__(self, x): return EFloat(float.__rsub__(self, float(x))) def __div__(self, x): return EFloat(float.__div__(self, float(x))) def __rdiv__(self, x): return EFloat(float.__rdiv__(self, float(x))) def __truediv__(self, x): return EFloat(float.__truediv__(self, float(x))) def __rtruediv__(self, x): return EFloat(float.__rtruediv__(self, float(x))) def __pow__(self, x): return EFloat(float.__pow__(self, float(x))) def __rpow__(self, x): return EFloat(float.__rpow__(self, float(x))) def __divmod__(self, x): return EFloat(float.__divmod__(self, float(x))) def __neg__(self): return EFloat(float.__neg__(self)) def __floordiv__(self, x): return EFloat(float.__floordiv__(self, float(x))) which works well for working with interactive Python. There are places on the web where I've read that people have to work their butts off trying to "trick" Excel or OpenOffice to do engineering notation, or there is some work-around that is purported to work if you use the right version of the spreadsheet. After many months of using my EFloat class extensively with lots of apps dealing with embedded engineering tasks, it dawns on me that what we really need is simply a new format specifier. I am thinking that if we simply added something like %n (for eNgineer) to the list of format specifiers that we could make life easier for engineers: ("%n" % 12345) == "12.345e+03" ("%n" % 1234) == "1.234e+03" ("%n" % 123) == "123e+00" ("%n" % 1.2345e-5) == "12.345e+06" Of course, the normal dot fields would be put to use to allow us to specify how many total digits or digits of precision we wanted, or if we want zero prepend. (whatever makes the most sense, and keeps the standard most like what is already in the language): ("%.12n" % 12345678) == "12.345678000000e+06" Do you think this idea has enough merit to make it to PEP status? --Keith Brafford
From: Chris Rebert on 26 Apr 2010 00:02 On Sun, Apr 25, 2010 at 8:36 PM, Keith <keith.brafford(a)gmail.com> wrote: > I am considering writing a PEP for the inclusion of an engineering > format specifier, and would appreciate input from others. > > Background (for those who don't already know about engineering > notation): > > Engineering notation (EN) is type of floating point representation. > The idea with EN is that the powers of 10 are all multiples of 3, > which correspond to the familiar Greek unit prefixes that engineers > use when describing the different sizes of all sorts of real-world > devices and phenomena: > > 1e-12 == pico > 1e-9 Â == nano > 1e-6 Â == micro > 1e-3 Â == milli > 1e+3 Â == kilo > 1e+6 Â == mega > 1e+9 Â == giga > > When people are talking about Ohms, Farads, Henries, Hz, and many > others, they routinely have to normalize to EN. Â Fancy calculators > from HP and TI routinely allow the users to go into engineering mode, > but mysteriously things like C, Python, Excel, etc. don't > > For instance, no one talks about 4.7e-5F, as they would rather see > 47e-6 (micro). Â Instead of 2.2e-2, engineers need to see 22.0e-3 > (milli). <snip> > There are places on the web where I've read that people have to work > their butts off trying to "trick" Excel or OpenOffice to do > engineering notation, or there is some work-around that is purported > to work if you use the right version of the spreadsheet. Relevant related information: The Decimal datatype supports engineering format directly: http://docs.python.org/library/decimal.html#decimal.Decimal.to_eng_string Cheers, Chris -- http://blog.rebertia.com
From: Steven D'Aprano on 26 Apr 2010 00:29 On Sun, 25 Apr 2010 20:36:22 -0700, Keith wrote: > I am considering writing a PEP for the inclusion of an engineering > format specifier, and would appreciate input from others. [...] > For instance, no one talks about 4.7e-5F, as they would rather see 47e-6 > (micro). Instead of 2.2e-2, engineers need to see 22.0e-3 (milli). I'd be cautious about making claims about "no one", because not everyone wants to see engineering notation. You may recall that the other common display format on scientific calculators is Scientific Notation, which *does* display 2.2e-2. > After many months of using my EFloat class extensively with lots of apps > dealing with embedded engineering tasks, it dawns on me that what we > really need is simply a new format specifier. > > I am thinking that if we simply added something like %n (for eNgineer) > to the list of format specifiers that we could make life easier for > engineers: I for one don't like %n. I already write %n for integer, at least now I get an error immediately instead of code that silently does the wrong thing. But I don't have a better idea of what letter to use. However, for good or ill the general consensus among the Python language developers is that % formatting is to be discouraged in favour of the format() method. For this reason, I expect that there will be zero (or negative) interest in extending the list of % format specifiers. But there may be some interest in adding a specifier to format(). http://docs.python.org/library/string.html#formatstrings It may be worth mentioning in the PEP that Decimals already have a method for converting to engineering notation, to_eng_string. -- Steven
From: Keith on 26 Apr 2010 00:42 On Apr 26, 12:02 am, Chris Rebert <c...(a)rebertia.com> wrote: > On Sun, Apr 25, 2010 at 8:36 PM, Keith <keith.braff...(a)gmail.com> wrote: > > I am considering writing a PEP for the inclusion of an engineering > > format specifier, and would appreciate input from others. snip > Relevant related information: > The Decimal datatype supports engineering format directly:http://docs.python.org/library/decimal.html#decimal.Decimal.to_eng_st... > > Cheers, > Chris Thanks for pointing that out. Does the engineering community get by with the decimal module? Even though this uses the to_eng_string() function, and even though I am using the decimal.Context class: >>> c = decimal.Context(prec=5) >>> decimal.Decimal(1234567).to_eng_string(c) '1234567' That is not an engineering notation string. --Keith Brafford
From: Keith on 26 Apr 2010 01:10
On Apr 26, 12:29 am, Steven D'Aprano <st...(a)REMOVE-THIS- cybersource.com.au> wrote: > On Sun, 25 Apr 2010 20:36:22 -0700, Keith wrote: >>no one talks about 4.7e-5F, as they would rather see 47e-6 >>(micro). Instead of 2.2e-2, engineers need to see 22.0e-3 (milli). >I'd be cautious about making claims about "no one" Good point, and I don't intend to belittle scientific computing folks for whom traditional floating point representation is expected. Nor am I suggesting that any of the six format specifiers that we already have for scientific notation (e, E, f, F, g, G) be altered in any way. I guess I wasn't clear about the F in the 4.7e-5F in the example. People doing engineering don't use 4.7e-5 Farads. They typically have to do extra work to get that number to print out correctly, as 47 e-6 Farads. The same goes for lots of signal processing entities. People doing things with Hz, seconds, you name it, have the same problem. --Keith |