[Tex/LaTex] How to add spaces at every X digit in a binary or hexadecimal number

formatting

I would like to format binary or hexadecimal numbers with a space separator at each 2 or 4 digit (or any other value like 8 digit or more).

A small picture is better than a long explanation, here is what I would like to do:

enter image description here

As you can see in this mwe, I use the fmtcount package with padzeroes:

    \documentclass{article}
    \usepackage[utf8]{inputenc}    
    \usepackage[T1]{fontenc}          
    \usepackage{fmtcount}
    \begin{document}
            Binary value : {\padzeroes[16]\binarynum{129}}$_{(2)}$ %
            should display 0000 0000 1000 0001$_{(2)}$

            Hexadecimal value: {\padzeroes[8]\Hexadecimalnum{65000}}$_{(16)}$ %
            should display  00 00 FD E8$_{(2)}$
    \end{document}

What I want to do is displaying numbers with various radix (2, 3, 7, 8, 10, 16) given a decimal number and format these numbers correctly with spaces and leading 0 (without having to perform the conversion by myself).

I already found some posts with similar questions, but none of them achieve this (they display number with thousand separators, like the numprint package, every 3 digits; or they do not make it automatic). Here are these posts :

EDIT two other linked questions:

I also prefer to use pdflatex.

Best Answer

A solution that optionally does conversion of the input given in decimal form; I can think to other improvements.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\printnumber}{O{}m}
 {
  \group_begin:
  \keys_set:nn { lauhub/printnumber } { #1 }
  \lauhub_print_number:n { #2 }
  \group_end:
 }

\tl_new:N \l_lauhub_number_tl
\tl_new:N \l_lauhub_output_tl
\int_new:N \l__lauhub_temp_int

\keys_define:nn { lauhub/printnumber }
 {
  padding  .int_set:N  = \l_lauhub_length_int,
  padding  .initial:n  = 0,
  radix    .int_set:N  = \l_lauhub_radix_int,
  radix    .initial:n  = 10,
  grouping .int_set:N  = \l_lauhub_grouping_int,
  grouping .initial:n  = 3,
  convert  .bool_set:N = \l_lauhub_convert_bool,
  convert  .default:n  = true,
  convert  .initial:n  = false,
 }

\cs_new_protected:Npn \lauhub_print_number:n #1
 {
  \tl_clear:N \l_lauhub_output_tl
  \bool_if:NTF \l_lauhub_convert_bool
   {
    \tl_set:Nx \l_lauhub_number_tl { \int_to_Base:nn { #1 } { \l_lauhub_radix_int } }
   }
   {
    \tl_set:Nn \l_lauhub_number_tl { #1 }
   }
  \prg_replicate:nn { \l_lauhub_length_int - \tl_count:N \l_lauhub_number_tl }
   {
    \tl_put_left:Nn \l_lauhub_number_tl { 0 }
   }
  \int_zero:N \l__lauhub_temp_int
  \tl_map_inline:Nn \l_lauhub_number_tl
   {
    \tl_put_right:Nn \l_lauhub_output_tl { ##1 }
    \int_incr:N \l__lauhub_temp_int
    \bool_if:nT
     {
      \int_compare_p:n
       {
        \int_mod:nn { \l__lauhub_temp_int } { \l_lauhub_grouping_int } == 0
       }
      &&
      \int_compare_p:n
       {
        \l__lauhub_temp_int < \l_lauhub_length_int
       }
     }
     {
      \tl_put_right:Nn \l_lauhub_output_tl { \, }
     }
   }
  \ensuremath
   {
    \mathrm{ \tl_use:N \l_lauhub_output_tl } \sb { ( \int_to_arabic:n { \l_lauhub_radix_int } ) }
   }
 }

\ExplSyntaxOff

\begin{document}

\printnumber[padding=16,grouping=4,radix=2]{10000001}

\printnumber[padding=16,grouping=4,radix=2,convert]{129}

\printnumber[padding=8,grouping=2,radix=16]{FDE8}

\printnumber[padding=8,grouping=2,radix=16,convert]{65000}

\end{document}

enter image description here

After setting the options, the input (possibly converted to the requested base) is padded to the left with zeroes. Then the token list is mapped: when the number of steps is a multiple of the value in grouping a thin space is added (except at the last step).