# siunitx round-half=even erratic behavior

I'm trying to create random exercises sheets (including answer) where students could practice rounding to the nearest integer. These exercises round the exact half to the nearest even number. E.g. 2.5 is rounded to 2 and 3.5 is rounded to 4.

I try to do it using the round-half=even option from the siunitx package but the results seem erratic. From the following MWE:

\documentclass{article}
\usepackage{siunitx}
\sisetup{round-half = even}

\begin{document}
$\num{2,6} \rightarrow \num[round-mode=places,round-precision=0]{2,6}$

$\num{3,6} \rightarrow \num[round-mode=places,round-precision=0]{3,6}$

$\num{12,6} \rightarrow \num[round-mode=places,round-precision=0]{12,6}$

$\num{13,6} \rightarrow \num[round-mode=places,round-precision=0]{13,6}$

$\num{14,6} \rightarrow \num[round-mode=places,round-precision=0]{14,6}$

\end{document}


I get

2.6 is rounded to 2 (wrong)

3.6 is rounded to 4 (true)

12.6 is rounded to 12 (wrong)

13.6 is rounded to 13 (wrong)

14.6 is rounded to 14 (wrong)

Does anyone knows why such a behavior? Is there a workabout?

From \listfiles, this is my version of siunitx

 siunitx.sty    2018/05/17 v2.7s A comprehensive (SI) units package


Edit

@Werner didn't have the same output as me, despite having the same siunitx version. Here is an image showing my texcode output and \listfiles • thanks @Werner for the edit except that 13.6 is rounded to 13 (which is really strange) – Alain Remillard Oct 9 '19 at 18:45
• I don't follow why you feel some of these are wrong: they are all the nearest even integer – Joseph Wright Oct 9 '19 at 18:49
• Interestingly, 2.6 is rounded to 2 but 2.61 to 3 ... – Zarko Oct 9 '19 at 19:01
• @JosephWright: I think there's an interpretation difference: half-round = even for you means round to the nearest even integer. To others, half-round = even only applied for when you have a tie, like in 2.5 > 2, or 13.5 > 13. In all other non-tie cases, regular round happens to the closest integer. – Werner Oct 9 '19 at 19:30
• I've checked my v3 code, which seems to get this right ... hmm ... another one of those things I need to finish v3 for :( – Joseph Wright Oct 9 '19 at 19:48

A temporary fix is

\ExplSyntaxOn
\cs_set_protected:Npn \__siunitx_number_process_places_none:n #1
{
\prop_get:NnNT \l__siunitx_number_in_prop { #1 -decimal } \l__siunitx_tmpa_tl
{
\int_compare:nNnTF { \tl_head:N \l__siunitx_tmpa_tl } > 4
{
\prop_get:NnNTF \l__siunitx_number_in_prop { #1 -integer }
\l__siunitx_tmpb_tl
{
\tl_set:Nx \l__siunitx_tmpb_tl
{ \int_eval:n { \l__siunitx_tmpb_tl + 1 } }
\bool_if:NF \l__siunitx_round_half_up_bool
{
\bool_lazy_and:nnT
{
\int_compare_p:nNn
{ 0 \tl_head:N \l__siunitx_tmpa_tl } = 5
}
{
\int_compare_p:nNn
{ 0 \tl_tail:N \l__siunitx_tmpa_tl } = 0
}
{
\int_if_odd:nT \l__siunitx_tmpb_tl
{
\tl_set:Nx \l__siunitx_tmpb_tl
{ \int_eval:n { \l__siunitx_tmpb_tl - 1 } }
}
}
}
}
{ \tl_set:Nn \l__siunitx_tmpb_tl { 1 } }
\prop_put:NnV \l__siunitx_number_in_prop
{ #1 -integer } \l__siunitx_tmpb_tl
}
{
\prop_if_in:NnF \l__siunitx_number_in_prop { #1 -integer }
{
\prop_put:Nnn \l__siunitx_number_in_prop
{ #1 -integer } { 0 }
}
}
}
\prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal }
\bool_if:NF \l__siunitx_process_int_to_dec_bool
{ \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal-marker } }
}
\ExplSyntaxOff


I will update the package on CTAN today.

• Thanks for the quick solution. And mostly thanks for the siunitxpackage. – Alain Remillard Oct 10 '19 at 18:26