# Changing tabularx column alignment partway through table

I have some very large and very small numbers being displayed in decimal notation (for a non-scientific audience). Normally—for small magnitude ranges—I would align on the decimal point with {r@{.}l}, but in this case I have to deal with about 20 orders of magnitude in the same table, so that becomes impractical. My real table has over twenty rows.

Currently all numbers can be right-aligned or left-aligned en-masse. I would like to right-align the positive powers (whole numbers), but left-align the negative powers (fractional numbers).

\begin{tabularx}{\textwidth}{>{\bfseries}clrX}
Name & Sci       & Decimal           & Notes \\
\hline
foo  & $10^{12}$ & 1 000 000 000 000 & Big number \\
bar  & $10^{5}$  &           100 000 & Fair size \\
\hline
baz  & $10^{-6}$ & 0.000 001         & Left-align these \\
qux  & $10^{-8}$ & 0.000 000 01      & numbers, please! \\
\end{tabularx}


I could do \multicolumn{1}{l}{0.000 0001} for each fractional number (or vice-versa for whole numbers)—and could perhaps even automate that I suppose—but as I haven't been at LaTeX very long[1], I'd like to learn the best practices before I start hacking.

## The question, restated

1 000 000 Whole numbers align right
10 000
100
0.01
0.000 1
0.000 001 Fractional (decimal) numbers align left


As I admit this might be an X-Y problem, I'll accept any elegant answer that can produce the desired output. I'll also accept edits to the question to clear up anything confusing.

1. Only about 20 years. Funny this never came up.
• Do fractional powers always have 0 before decimal dot? – Przemysław Scherwentke Dec 27 '15 at 16:51
• @PrzemysławScherwentke Yes, the negative powers always begin with 0.. – type_outcast Dec 27 '15 at 16:59

You can exploit siunitx for easier input and define commands for left and right alignment:

\documentclass{article}
\usepackage{tabularx,siunitx}

\NewDocumentCommand\rnum{O{}m}{%
\mbox{}\hspace{0pt plus 1filll}\num[#1]{#2}%
}
\NewDocumentCommand\lnum{O{}m}{%
\num[#1]{#2}\hspace{0pt plus 1filll}\mbox{}%
}

\begin{document}

\noindent
\begin{tabularx}{\textwidth}{>{\bfseries}clcX}
Name & Sci       & Decimal           & Notes \\
\hline
foo  & $10^{12}$ & \rnum{1000000000000} & Big number \\
bar  & $10^{5}$  &        \rnum{100000} & Fair size \\
\hline
baz  & $10^{-6}$ & \lnum{0.000001}      & Left-align these \\
qux  & $10^{-8}$ & \lnum{0.00000001}    & numbers, please! \\
\end{tabularx}

\end{document}


• +1, great suggestion! Forgive the potentially silly question, but what is the difference of using your \hspace\mbox method versus something simple like \newcommand{\lnum}{\multicolumn{1}{l}}? – type_outcast Dec 27 '15 at 17:15
• @type_outcast You can so accommodate the optional argument to \num, just in case you need it – egreg Dec 27 '15 at 17:19

You could use collcell to collect the content and test the value. (The "Decimal" is braced to avoid that it is tested too).

\documentclass{article}
\usepackage{tabularx}
\usepackage{siunitx}
\usepackage{collcell}

\ExplSyntaxOn
\newcolumntype{E}{>{\collectcell \my_is_braced_input:n }c<{\endcollectcell}}

\cs_new:Npn \my_align_numbers:n #1\scan_stop:
{
\fp_compare:nTF { #1 < 1 }
{\num{#1}\hfill\mbox{}}
{\mbox{}\hfill\num{#1}}
}

\cs_new:Nn \my_is_braced_input:n
{
\peek_catcode:NF \c_group_begin_token
{\my_align_numbers:n}
#1\scan_stop:
}
\ExplSyntaxOff

\sisetup{group-digits}
\begin{document}

\noindent
\begin{tabularx}{\textwidth}{>{\bfseries}clEX}
Name & Sci       & {Decimal} & Notes \\
\hline
foo  & $10^{12}$ & 1000000000000 & Big number \\
bar  & $10^{5}$  &        100000 & Fair size \\
\hline
baz  & $10^{-6}$ & 0.000001      & Left-align these \\
qux  & $10^{-8}$ & 0.00000001    & numbers, please! \\
\end{tabularx}

\end{document}