Sunday, January 29, 2012

How to Format Numbers in Engineering Format using C#

I once had a nice Network Analyzer that worked very well, except for one very annoying thing. The display was in Scientific Notation, not Engineering Notation. So for instance when it displayed 100 Hz it actually printed on the screen 1.00E+02 Hz, not the more familiar 100 Hz or even 100.0E+00 Hz. Since Engineers think in terms of numbers grouped in powers of 3, like: Milli, Nano, Micor, Pico, etc.... this was is rather annoying.

But what about today - today we write engineering programs on a PC that doesn't know about engineering notation either, which is rather crazy since HP Calculators have known how to do this since the original HP-35 from 1972. So here it is 2012 and our PC's still can't do Engineering notation nativity.

This is pretty easily solved and I have been writing these programs myself since my first Apple ][, today I use a PC and program in C# and I thought I would share my current method of converting a Double to Engineering Notation in C#.

There are many ways to do this from: Converting the number to a string first and manipulating the string into Engineering Notation, to iterating in on the number format in a loop. The method That I will present here is the tried and true use of LOG10() to find the magnitude of a number, then grouping that by threes to find the proper range, looking that range up in a table and finally formatting the number with the proper number of significant digits.

The routine below is a small static class that works with version of 4.0 of C# .NET. No special tricks are used. (Note:If you remove the optional arguments, the routine will work with earlier versions of C#)

To call the routine you can just use the format,

String snum = ToEngineeringFormat.Convert(number, sig_digits [Optional], units [Optional]);

Where the number is the number to convert to a string in scientific notation. sig_digits is the number of significant digits to display in the resulting string. And units is the units string to append to the resulting string. This would be like “Hz” or “F” or “Tesla”, etc...

sig_digits and units are setup as optional parameters in the routine that I use.

In engineering format it really only makes sense to have a minimum of 3 Significant Digits in the result.

This is because you can have 3 digits in a number before or after the decimal place inside of one range. For instance you can have 999 Hz and this wouldn't probably make sense to round to one or two digits. If you need this - you probably need to round your numbers first using some bounding method.


Some Examples,

Significant digits set to 3
Number Converted result
1.234567 => 1.23
12.34567 => 12.3
123.4567 => 123
1234.567 => 1.23 k
12345.67 => 12.3 k
123456.7 => 123 k
1e-10 => 100 p
1.111e-9 => 1.11n
1.234e+11 => 123 G

Significant Digits set to 5
1234.5678 => 1.2346 k {Note: the trailing 5 was rounded up to 6}
1.2345678e-5 => 12.346 u {Note: the trailing 5 was rounded up to 6}


1 comment:

  1. Here's a routine that I have been using for many years. It is still on the web!
    http://www.cs.tut.fi/~jkorpela/c/eng.html

    ReplyDelete