File Exchange

image thumbnail

NUM2ENG: Fast number to engineering notation (SI) conversion

version 1.2.4.3 (20.3 KB) by Roman Müller-Hainbach
Convert numbers to engineering notation.

1 Download

Updated 29 Nov 2017

View License

Engineering notation is similar to scientific notation, except that
the exponent power of 10 is always an integer multiple of 3, and the
mantissa is scaled so that it lies inside [0,1000). The range of
exponents for which a SI-prefix is available goes from 10^-24 to 10^24.
Examples (of scalar inputs):
- num2eng(4700)
ans = '4.7 k'
- num2eng(82000,[1 4], 'FullName',true)
ans = '82 kilo'
- num2eng(1000,4)
ans = '1.000 k'
- num2eng(-3.527e6,3)
ans = '-3.53 M'
- num2eng(9999,[1 2])
ans = '10 k'
- num2eng(999,3)
ans = '999'
- num2eng(100, 'ForceExponent',3)
ans = '0.1 k'
- [ 'Distance: ', num2eng(4.2e4, 'FullName',true, 'Unit','meter') ]
ans = 'Distance: 42 kilometers'
- [ 'Distance: ', num2eng(1e3, 'FullName',true, 'Unit','meter') ]
ans = 'Distance: 1 kilometer'
Syntax:
eng = num2eng(num) returns a string containing the engineering
notation of 'num'. 'num' can be any numerical scalar, vector or
matrix. If the input isn't scalar the output is a cellstring with
the same shape as in the input. The number of significant figures
defaults to up to 5 ( 'sigfigs'=[1 5] ). The output contains a
space between the number and the prefix part, but doesn't have
trailing whitespaces.
__ = num2eng(num,sigfigs) gives control over the number of
significant figures in the output. sigfigs must be positive. It can
either be a scalar or two-element vector describing [min max]. In
the latter case trailing zeros are, if applicable, omitted.
__ = num2eng(__,Name,Value,...) allows the user to specify one or
more of these options to take effect:
- 'SynchronizeExponents' : (false) / 'min' / 'max' / 'median'
Causes the outputs to all have the same SI-prefix/exponent. The
value for this ('min','max' or 'median') determines what
SI-prefix is chosen when values in num are of varying orders of
magnitude.
- 'ForceExponent' : (false) / [exp] / [min max]
Forces all outputs to have a given exponent or confines them
within a given minimum and maximum exponent range. Exponent
values must be multiples of 3. If this option is present,
'SynchronizeExponents' is ignored.
- 'DistinctOutput' : (false) / true
Ensures distinct outputs. The maximum number of significant
figures is increased as needed to achieve this.
- 'OmitSpace' : (false) / true
Omits the whitespace between the number and the SI-prefix. This
option is ignored if there are two output arguments.
- 'FullName' : (false) / true
Writes prefixes as full names instead of one-letter
abbreviations.

- 'Unit' : (false) / 'unit' / {'unit1','unit2',...}
Appends the given unit string(s) to the output. If a cell-array
is provided, it must have the same number of elements as the
'num' input. If necessary 'reshape' is called to match the
shape of 'num'. Each unit string gets processed by 'strtrim'.
Written out units should be given in singular form. Whenever
the printed value is not '1', a plural 's' is appended to the
unit string. If there are two output arguments and the exponent
is forced to a single value ( via the option 'ForceExponent'
with a single exponent or via 'SynchronizeExponents' ), '(s)'
or 's' is appended to the second output, depending on if some,
but not all, or all printed values are not '1'. No plural 's'
is appended if the unit string already ends with a 's'.

- 'NoPlural' : (false) / true
Disables the automatic appending of a plural 's' to the unit.
This option is ignored if full names aren't effective aswell.

All options default to false, which disables them. The option
names can be abbreviated as long as they remain unambigious.
A working set of short names is 'sync', 'force', 'distinct',
'omit', 'full', 'unit' and 'nop'. The shortest possible set of
names is 's', 'fo', d', 'fu', 'u' and 'n'.

[num,sip] = num2eng(num,__) returns number and SI-prefix part
separately. Neither part contains a whitespace. If the input 'num'
isn't scalar, the output 'num' is a cellstring. 'sip' is a
cellstring if the input 'num' isn't scalar and the exponent in the
output isn't forced to a single value ( via the options
'SynchronizeExponents' or 'ForceExponent',[exp] ).

For even more information take a look at the help block inside num2eng.m.

Comments and Ratings (5)

"k" and "kilo" are not engineering notation. Engineering is strictly X.YYYYexp(J) format . ISO standards recommend against things like "4.7 k" for unitless items. Adding actual dimension names (length, coulombs, etc) is a separate business.

@Stephen Cobeldick
Thank you for the feedback you have provided me with. I addressed your points in my version 1.2.
I suspect your performance testing was done on scalar inputs. This function does exhibit considerable overhead in such cases. With multiple numbers to convert though, a vectorized call to my implementation is indeed faster than all other implementations I can find on FEX, which have to be used with for-loops or arrayfun.

Disclaimer: In the end I could not find any FEX submission that gave the correct outputs for the wide range of test-cases that I tried, so I ended up writing my own function. It can be found here:

http://www.mathworks.com/matlabcentral/fileexchange/33174

PS: the values outside the suffix range are also missing a trailing space character, e.g. 1e32 -> '100 e30', but should be '100e30 ' (correcting my comment below). A trailing space is required to allows direct concatenation of the units to give the correct SI-compliant string, e.g. '1 k' + 'N' -> '1 kN', and thus also '100e30 ' + 'N' -> '100e30 N'.

A nicely presented and clearly explained function, with an H1 line, clear help and description. Thorough input checking and plenty of options make it very handy.

The code could be tidied up, especially the awkward indentation and trailing spaces during the input checking, and the strange order of SWITCH cases: neither alphabetical nor by value.

However it does not process Inf, -Inf, NaN: someone's code might fail simply because this cannot handle Inf inputs. Better to let the user decide if they want Inf/NaN to be an error or not.

Contrary to what the author states in the title, this is the slowest of all the "number to SI prefix" submissions that I have tested (seven submissions so far!), averaging at slightly more than 2 ms per call. In contrast most of the other submissions I tested run at less than 0.5 ms per call. The significant position of the word "Fast" in the title is very misleading, and significantly brought my rating down. Did the author actually compare the run-time against any other num to SI/metric submissions?

Incorrect outputs also occur in some cases. When the input value is rounded up to the next SI prefix this function uses the wrong suffix. For example: num2eng(999,1) returns '1000', but it should be '1 k', or num2eng(999999,3)->'1000 k', but it should simply be '1 M'. And in that situation the number of digits is also incorrect, for example: num2eng(999999,4)->'1000.0 k', which has five significant figures, not the requested four. When there is no suffix (values smaller than 1e-25 or larger than 1e30) this functions returns an E-notation number, but bizarrely adds a space character between the values and the 'e' character, e.g. 1e32 -> '100 e30', but should be '100e30', which is the standard way of writing E-notation.

Altogether a nice function with potential to be a great function. I like the options.

Updates

1.2.4.3

typo bug fix

1.2.4.2

Fixed mistreatment of input values that are very near to zero.

1.2.4.1

Updated thumbnail

1.2.4.0

- Added automatic pluralization of written out units
- Added 'NoPlural' option
- Added examples to description
- Improved performance slightly

1.2.3.1

Improved input parsing performance

1.2.3.0

Improved issuing of warnings

1.2.2.2

Improved performance for scalar and non-scalar inputs.

1.2.2.1

Fixed wrong spacing for numbers that are printed in exponential form.

1.2.2.0

- Added 'Unit' option
- Renamed 'FullNames' option to 'FullName'

1.2.1.1

Fixed title again, FEX is acting up

1.2.1.0

- Increased performance slightly for scalar inputs
- Updated description with performance considerations
- Fixed handling of inputs in a few edge cases

1.2.0.1

Fixed wrong title

1.2.0.0

- Fixed output in situations where the number of digits increased due to rounding
- Added support for NaN and infinite values
- Minor performance optimizations

1.1.1.0

- Fix bug with second output
- Improve description

1.1.0.0

- Added two-outputs form
- Fixed and updated description

MATLAB Release Compatibility
Created with R2007b
Compatible with any release
Platform Compatibility
Windows macOS Linux
Acknowledgements

Inspired by: Number to Scientific Prefix