Engineering mode for number formatting

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

you get

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! 🙂

(pastebin link)

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[2]=='0':
        s=s[0:2]
    if p==0 and s[1]=='0':
        s=s[0:1]
    if p==1 and s[2]=='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]

Example output:

     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
Advertisements

One thought on “Engineering mode for number formatting

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s