[Tex/LaTex] How to typeset numbers in scientific notation without using a dedicated package such as siunitx

formatting

My thesis includes numbers such as, 9.368e-03, OR 9.368E-03, spread throughout the main text. I would like to typeset them in the form of a scientific notation such as – 9.683 x 10^-3.

However, since I am using TeX Live 2009 on an equally ancient machine and since my thesis document has grown considerably large, I do not want to burden the system by using any of the dedicated packages (e.g. siunitx), just to typeset a few numbers properly.

Is there a simpler way by which I can typeset my numbers in the desired format without using a dedicated scientific notation package?

Best Answer

For the simple format given, a short chain of dedicated commands can pick up the number. I'm assuming here that the numbers will never have too many digits for TeX's \number primitive, which I'm using to trim off any leading zeros.

\documentclass{article}
\makeatletter
\newcommand*{\num}[1]{%
 \ensuremath{%
   \num@auxi#1ee\stop
  }%
}
\newcommand*\num@auxi{}
\def\num@auxi#1e#2e#3\stop{%
  \ifx\relax#2\relax
    \expandafter\num@auxii
  \else
    \expandafter\num@auxv
  \fi
    {#1}{#2}%
}
\newcommand*\num@auxii[2]{%
  \num@auxiii#1EE\stop
}
\newcommand*\num@auxiii{}
\def\num@auxiii#1E#2E#3\stop{%
  \ifx\relax#2\relax
    \expandafter\num@auxiv
  \else
    \expandafter\num@auxv
  \fi
    {#1}{#2}%
}
\newcommand*\num@auxiv[2]{%
  \number #1 
}
\newcommand*\num@auxv[2]{%
  \number #1 \times 10^{\number #2 }%
}
\makeatother
\begin{document}
\num{9.386e-03}
\num{9.386E-03}
\num{9.386}
$\num{9.386e-03}$
\end{document} 

If you want to retain leading zeros and any leading + symbols the code can be slightly simplified

\documentclass{article}
\makeatletter
\newcommand*{\num}[1]{%
 \ensuremath{%
   \num@auxi#1ee\stop
  }%
}
\newcommand*\num@auxi{}
\def\num@auxi#1e#2e#3\stop{%
  \ifx\relax#2\relax
    \expandafter\num@auxii
  \else
    \expandafter\num@auxiv
  \fi
    {#1}{#2}%
}
\newcommand*\num@auxii[2]{%
  \num@auxiii#1EE\stop
}
\newcommand*\num@auxiii{}
\def\num@auxiii#1E#2E#3\stop{%
  \ifx\relax#2\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\num@auxiv
  \fi
    {#1}{#2}%
}
\newcommand*\num@auxiv[2]{%
  #1 \times 10^{#2}%
}
\makeatother
\begin{document}
\num{9.386e-03}
\num{9.386E-03}
\num{9.386}
$\num{9.386e-03}$
\end{document}

More complex parsing is possible without using siunitx, and indeed the numprint package offers quite a bit of this in a package that has been available for many years.


How does the above code work? The outer macro

\newcommand*{\num}[1]{%
 \ensuremath{%
   \num@auxi#1ee\stop
  }%
}

simply grabs the entire input, and inserts it after the first internal macro \num@auxi. The latter is going to look for a e, so we make sure there will be one to find by including ee after the input. (I'll come back to why two e tokens later.)

Macro \num@auxi comes next

\def\num@auxi#1e#2e#3\stop{%
  \ifx\relax#2\relax
    \expandafter\num@auxii
  \else
    \expandafter\num@auxv
  \fi
   {#1}{#2}%
}

Here we have a delimited macro. Everything up to the first e will be grabbed as #1, everything between that and the second e as #3 and the remainder up to \stop as #3. There are two outcomes. If the original input contains an e then #1 will be the mantissa, #2 will be the exponent and #3 is junk. On the other hand, if there was no e then #1 is the entire number and #2 is empty. We test for that using \ifx\relax#2\relax (true if #2 is empty) and branch accordingly.

If e was not found, there is a bit of set up to do the same again but looking for an E. Once that search is done, we have two outcomes: a number with no exponent or a number with exponent. The first case is handled by

\newcommand*\num@auxiv[2]{%
  \number #1 
}

Due to the way I've set up the code, this receives two arguments, the mantissa and the exponent. We know the latter is empty (it's only there to act as a 'throw away') so we just insert #1 (the mantissa). I've included \number before it, which means TeX will 'tidy up' the input, removing any leading zeros or + signs.

If there is an exponent then the code

\newcommand*\num@auxv[2]{%
  \number #1 \times 10^{\number #2 }%
}

is used: this inserts the mantissa then the exponent with correct formatting. I could have combined the last two macros and included a test on #2 there, but I felt it was clearer with separate paths.


You might wonder in the above why we have

\def\num@auxi#1e#2e#3\stop{%

rather than just using one e (as the input can only have one). It all comes down to making the tests as short as possible. With a definition

\def\num@auxi#1e#2\stop{%

you might think we'll be OK. However, there's a problem. If I do

\num@auxi#1\stop

and there is no e in the input then TeX will complain as the parameters for \num@auxi will not match properly. So instead we need to do

\num@auxi#1e\stop

to make sure that there is always an e to find. However, if the input also contains an e then \num@auxi ends up splitting so that #1 is the mantissa but #2 is the exponent plus that trailing e. We could allow for that will a clean-up step, but it's easier to use two e tokens and use definition

\def\num@auxi#1e#2e#3\stop{%

used as

\num@auxi#1ee\stop

In this case, if there is no e in the input we get #1 as the mantissa, while #2 and #3 are empty. On the other hand, if there was an e in the input then #1 is the mantissa, #2 is the exponent and #3 mops up the stray e (we always discard #3). So working this way we need only the one macro to do the work.