One of the most crucial issues in informatics is I/O, and more specifically parsing and printing formatted text. And one of the most classic tools for outputting formatted numbers is the printf function, where a formatting string specifies how each number should be printed.
The format string is based on the ‘%’ codes that let you control field size, alignment, fill character, precision et cereta. For floating point numbers you also have the choice between the normal and the scientific modes. The normal mode just prints the digits with the decimal point where is should be. The scientific mode is more directed for very large and very small numbers, and use the mantissa / exponent notation.
HP calculators (as well as many other scientific calculator brands…) have these two formatting options too, straight numbers or mantissa/exponent notation, but they also offer a third option, what they call the engineering mode. Engineering format is like the scientific, but instead of normalizing by the largest digit and showing you a mantissa like 5.7631e+4, it rounds at exponents that are multiples of three. So instead of
3.1416e+0 3.1416e+1 3.1416e+2 3.1416e+3 3.1416e+4 3.1416e+5 3.1416e+6
3.1416e+0 31.416e+0 314.16e+0 3.1416e+3 31.416e+3 314.16e+3 3.1416e+6.
It seems too subtle, but I do like this very much, specially when doing engineering! It really helps to feel the magnitude of the numbers better. And it is also the way we label electronic components and all kinds of stuff, using the so-called SI prefix, which are greek words that represent thousands of the previous unit. You know, the “kilo, mega, giga, tera” and “mili, micro, nano, pico”. People working with computers are certainly not stranger to the need to express megabytes and kilobits and other quantities like this. In fact, it is puzzling that things like octal notation are so easy to obtain while this very well established habit of using only exponents that are multiple of three is completely ignored.
It’s been a while that I started to feel that the formatting functions in our programming languages, the printfs all around, seriously lack an “engineering format” option, like scientific calculators offer. That’s why I finally started to make my own formatting function the other day, and plan to submit to everyone eventually. (Starting with the Python and numpy crowd…)
The routine I pasted here does more than using the correct exponents… I also printed the letter corresponding to the prefix, and replaced the decimal point by the letter, like it’s done in electronic component labeling, for example. It looks crazy, but sometimes I really feel like using something more compact like this… Of course for the general use I’ll prefer just something like a %e notation with the rounded exponents. But anyway, here is one example of an output with my own personal crazy formatting:
k(H) k(jacoH) k(condH) 5.70e+06 1.70e+03 8.24e+02 4.51e+13 4.02e+06 9.41e+05 k(H) k(jacoH) k(condH) 5M69 1k7 823 45T 4M 940k
So here is the code. As always, it is still very crude but already does the job. Have fun! 🙂
from pylab import * def engprint(f): E = int(floor( log10(f) )) z = E/3 p = E-3*z k = f *1e2 / 1e3**z s = ('%d'%k)[0:3] if p==0 and s=='0': s=s[0:2] if p==0 and s=='0': s=s[0:1] if p==1 and s=='0': s=s[0:2] gregos=['y','z','a','f', 'p', 'n', 'u', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ] mark = gregos[z+8] if z==0 and len(s[p+1:])>0: mark='.' return s[0:p+1]+mark+s[p+1:]
UPDATE: A more “sane” implementation, that prints a normal floating-point followed by the SI prefix,
def engprint(f, precision=3): E = int(pylab.floor( pylab.log10(f) )) z = E/3 p = E-3*z k = pylab.floor(0.5+ f * 10.**(precision-E) ) s = ('%d'%k)[0:precision+1] gregos=['y','z','a','f', 'p', 'n', 'u', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ] return s[0:p+1]+'.'+s[p+1:]+gregos[z+8]
314.16n 3.1416u 31.416u 314.16u 3.1416m 31.416m 314.16m 3.1416 31.416 314.16 3.1416k 31.416k 314.16k 3.1416M 31.416M 314.16M 3.1416G