# 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).

## 2 Answers

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