# siunitx decimals only for numbers below 1

Suppose I have the following table

\documentclass{article}
\usepackage{siunitx}
\begin{document}

\begin{table}
\begin{tabular}{S[table-alignment=right,
round-mode=places,
round-precision=1,
table-format=5.3,
zero-decimal-to-integer]}
{title}  \\
11111    \\
11.11    \\
0.11     \\
\end{tabular}
\end{table}

\end{document}


and I would like to round the numbers such that numbers above 1 are rounded to integers and numbers below 1 are rounded to first decimal. The result here would be 11111, 11, 0.1.

I have tried the following combinations, which yielded undesirable results

round-mode=figures and round-precision=1: 10000, 10, 0.1
round-mode=figures and round-precision=5: 11111, 11.110, 0.11000
round-mode=places  and round-precision=1: 11111, 11.1, 0.1


but I cannot figure out the right settings to get what I need (and hope to be common enough that it is possible in siunitx).

If this is only for use in tables then you can use pgfplotstable and preprocess the numbers. Below I define a new key round int which provides the preprocessing.

\documentclass{article}

\usepackage{siunitx,pgfplotstable}
\pgfplotsset{compat=1.17}

\begin{document}

\makeatletter
\pgfplotsset{table/round int/.style={%
/pgfplots/table/preproc cell content/.append code={%
\pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfmathresult
\ifx\pgfmathresult\pgfutil@empty
\else
\pgfmathparse{abs(\pgfmathresult) > 1 ? round(\pgfmathresult) : \pgfmathresult}%
\pgfkeyslet{/pgfplots/table/@cell content}\pgfmathresult
\fi}}}
\makeatother

\pgfplotstabletypeset[multicolumn names,
columns/0/.style={column name={title},
string type,
column type={S[table-alignment=right,
round-mode=places,
round-precision=1,
table-format=-5.1,
zero-decimal-to-integer]},
round int
}
]{
11111
11.11
11.85
0.11
0.19
-10.2
-10.8
}

\end{document}


Unfortunately the standard preproc/expr included with pgfplotstable has some settings that are not appropriate for your data. The above code is based on how preproc/expr is implemented in that package.

If you want the numbers right-aligned in the column, just replace the table-format argument to the S column with table-parse-only:

\documentclass{article}

\usepackage{siunitx,pgfplotstable}
\pgfplotsset{compat=1.17}

\begin{document}

\makeatletter
\pgfplotsset{table/round int/.style={%
/pgfplots/table/preproc cell content/.append code={%
\pgfkeysgetvalue{/pgfplots/table/@cell content}\pgfmathresult
\ifx\pgfmathresult\pgfutil@empty
\else
\pgfmathparse{abs(\pgfmathresult) > 1 ? round(\pgfmathresult) : \pgfmathresult}%
\pgfkeyslet{/pgfplots/table/@cell content}\pgfmathresult
\fi}}}
\makeatother

\pgfplotstabletypeset[multicolumn names,
columns/0/.style={column name={title},
string type,
column type={S[table-alignment=right,
round-mode=places,
round-precision=1,
zero-decimal-to-integer,
table-parse-only]},
round int
}
]{
11111
11.11
11.85
0.11
0.19
-10.2
-10.8
}

\end{document}

• Interesting package! Is there a way of making all values right-aligned, such that the 1 in 0.1 is below the 2 in 12? – bumblebee Apr 29 '20 at 12:37
• @bumblebee Do want all numbers aligned to the right in the column, regardless of whether they are decimals or not? – Andrew Swann Apr 29 '20 at 12:52
• @bumblebee Such an example now added. – Andrew Swann Apr 29 '20 at 13:42

If you need to be able to use such a feature both in a table and outside in the text, you can make use of the math features in pgfmath to define the \MyRoundMacro:

\newcommand*{\MyRound}[1]{%
\pgfmathtruncatemacro{\@IntegerComponent}{abs(#1)}%
\ifnum\@IntegerComponent=0
\num[round-mode=places, round-precision=1]{#1}%
\else
\num{\@IntegerComponent}%
\fi
}%


You can either use this directly for each entry in the table or use the collcell package to define a custom column type R and use that:

\newcolumntype{R}{>{\collectcell\MyRound}r<{\endcollectcell}}


where the r is the desired column alignment.

The tables produced by the MWE below are as desired:

## Notes:

• Using the R column type requires that you wrap any not numerical content (such as the title lines) within a  \multicolumn{1}{c}{}.

## Code:

\documentclass{article}
\usepackage{siunitx}
\usepackage{collcell}% Needed only if desire to use the R column type defined below
\usepackage{pgfmath}

\begin{document}

\makeatletter
\newcommand*{\MyRound}[1]{%
\pgfmathtruncatemacro{\@IntegerComponent}{abs(#1)}%
\ifnum\@IntegerComponent=0
\num[round-mode=places, round-precision=1]{#1}%
\else
\num{\@IntegerComponent}%
\fi
}%
\makeatother

\newcolumntype{R}{>{\collectcell\MyRound}r<{\endcollectcell}}

In a table the \verb|R| column type (requires non data entries to be wrapped in a \verb|\multicolumn|):

\begin{tabular}{R}
\multicolumn{1}{c}{\bfseries title}  \\
11111    \\
11.11    \\
0.11     \\
\end{tabular}

Can use the \verb|\MyRound| macro directly in a table and
outside of a table:

\begin{tabular}{r}
{\bfseries title}  \\
\MyRound{11111}    \\
\MyRound{11.11}    \\
\MyRound{0.11}     \\
\end{tabular}

Outside of a table:

\MyRound{11111}\par
\MyRound{11.11}\par
\MyRound{0.11}\par

\end{document}

• This looks interesting, too. The in-table solution looks simple enough that it doesn't interfer with other table settings. However, the 0.11 (and all numbers smaller than 1) should be rounded to the first decimal. – bumblebee May 1 '20 at 12:19
• @bumblebee: Have updated the answer to apply the appropriate options to \num{} so that 0.11 is displayed as 0.1. – Peter Grill May 1 '20 at 16:48