Is it possible to re-group every 4 digits in a number with siunitx package?

There's currently no support for this in siunitx. You can do it with some different code:

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

\ExplSyntaxOn

\NewDocumentCommand{\groupfour}{O{,}m}
 {
  \mikew_groupfour:nn { #1 } { #2 }
 }

\tl_new:N \l_mikew_groupfour_separator_tl
\tl_new:N \l_mikew_groupfour_number_tl

\cs_new_protected:Nn \mikew_groupfour:nn
 {
  \tl_set:Nn \l_mikew_groupfour_separator_tl { {#1} }
  \tl_set:Nx \l_mikew_groupfour_number_tl { #2 }
  \tl_replace_all:Nnn \l_mikew_groupfour_number_tl { ~ } { }
  \tl_reverse:N \l_mikew_groupfour_number_tl
  \regex_replace_all:nnN
   { [0-9]{4} } % search
   { \0 \c{l_mikew_groupfour_separator_tl} } % replace
   \l_mikew_groupfour_number_tl % token list
  \tl_reverse:N \l_mikew_groupfour_number_tl
  \regex_replace_once:nnN
   { \A \c{l_mikew_groupfour_separator_tl} }
   { }
   \l_mikew_groupfour_number_tl
  \tl_use:N  \l_mikew_groupfour_number_tl
 }

\ExplSyntaxOff

\begin{document}

\groupfour{ 123456789 }

\groupfour[\,]{1 2345 6789}

$\groupfour{12345678}$ % test for math mode

\end{document}

This reverses the input, after removing blank spaces; then after every group of four digits, the separator is inserted (in symbolic form); the string is reversed again and a leading separator is removed.

You can change the separator by calling \groupfour[<separator>]{<number>}.

enter image description here

An extended version for dealing also with decimal numbers. In the decimal part, groups of four digits are separated by thin spaces. It wouldn't be difficult to change it, according to needs.

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

\ExplSyntaxOn

\NewDocumentCommand{\groupfour}{O{,}m}
 {
  \mikew_groupfour:nn { #1 } { #2 }
 }

\tl_new:N \l_mikew_groupfour_separator_tl
\tl_new:N \l_mikew_groupfour_number_tl
\seq_new:N \l_mikew_groupfour_parts_seq

\cs_new_protected:Nn \mikew_groupfour:nn
 {
  \tl_set:Nn \l_mikew_groupfour_separator_tl { {#1} }
  \regex_split:nnN { \. } { #2 } \l_mikew_groupfour_parts_seq
  \tl_set:Nx 
   \l_mikew_groupfour_number_tl
   { \seq_item:Nn \l_mikew_groupfour_parts_seq { 1 } }
  \tl_replace_all:Nnn \l_mikew_groupfour_number_tl { ~ } { }
  \tl_reverse:N \l_mikew_groupfour_number_tl
  \__mikew_groupfour_replace:
  \tl_reverse:N \l_mikew_groupfour_number_tl
  \tl_use:N  \l_mikew_groupfour_number_tl
  \int_compare:nT { \seq_count:N \l_mikew_groupfour_parts_seq > 1 }
   {
    \tl_set:Nn \l_mikew_groupfour_separator_tl { {\,} }
    . % print the decimal point
    \tl_set:Nx 
     \l_mikew_groupfour_number_tl
     { \seq_item:Nn \l_mikew_groupfour_parts_seq { 2 } }
    \__mikew_groupfour_replace:
    \tl_use:N  \l_mikew_groupfour_number_tl
   }
 }

\cs_new_protected:Nn \__mikew_groupfour_replace:
 {
  \regex_replace_all:nnN
   { [0-9]{4} } % search
   { \0 \c{l_mikew_groupfour_separator_tl} } % replace
   \l_mikew_groupfour_number_tl % token list
  \regex_replace_once:nnN
   { \c{l_mikew_groupfour_separator_tl} \Z }
   { }
   \l_mikew_groupfour_number_tl
 }

\ExplSyntaxOff

\begin{document}

X\groupfour{ 123456789 }X

X\groupfour[\,]{1 2345 6789}X

X$\groupfour{12345678}$X

X\groupfour{1234567890.12345678}X

\end{document}

enter image description here


For the sake of variety, here's a LuaLaTeX-based solution. It's very similar to to the one given in this answer. The solution defines a user macro called \groupfour, which invokes a Lua function that does the actual work. If the number (the argument of \groupfour) contains a decimal part, no commas are inserted in the decimal portion.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{siunitx}
\usepackage{luacode}
\begin{luacode}
function groupfour ( s )
    z = ""
    -- Check if number contains a decimal part. If so, don't
    -- insert commas in the decimal part.
    n = string.find ( s, "%." ) 
    if n then
       -- Set aside decimal part of number in string "z"
       z = string.sub ( s , n )
       s = string.sub ( s , 1 , n-1 )
    end 
    t = ""
    while string.len ( s ) > 4 do
        t = "{,}" .. string.sub ( s, -4 ) .. t
        s = string.sub ( s , 1, -5 ) 
    end
    tex.sprint ( s .. t .. z )
end
\end{luacode}
\newcommand\groupfour[1]{\directlua{groupfour(\luastring{#1})}}

\begin{document}
\num[group-separator={,}]{123456789}

\groupfour{123456789}
\end{document}

Tags:

Siunitx