# How to add spaces at every X digit in a binary or hexadecimal number?

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:

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.

## 2 Answers

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}


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

• Wow, thanks ! It even does what I did not asked (but I needed) ! – lauhub Feb 25 '15 at 13:55

It requires the output to be set in a fixed-width font (which some would consider preferable). I do it by successively trimming the output of \padzeroes, using \chop{number}{string}.

\documentclass{article}
%\usepackage[utf8]{inputenc}
%\usepackage[T1]{fontenc}
\usepackage{fmtcount}
\usepackage{trimclip,ifthen}
\newsavebox\numberbox
\newlength\boxoffset
\newcommand\chop[2]{%
\bgroup\ttfamily%
\setbox0=\hbox{0}%
\savebox\numberbox{#2}%
\boxoffset=0pt%
\whiledo{\lengthtest{\boxoffset<\wd\numberbox}}{%
\clipbox{\boxoffset+0pt 0pt \wd\numberbox-\boxoffset-#1\wd0 -1pt}{\usebox{\numberbox}}%
\addtolength{\boxoffset}{#1\wd0}%
\ifdim\boxoffset<\wd\numberbox\ \fi%
}\unskip\egroup%
}
\begin{document}
Binary value : {\chop{4}{\padzeroes[16]\binarynum{129}}}$_{(2)}$ %

Hexadecimal value: {\chop{2}{\padzeroes[8]\Hexadecimalnum{65000}}}$_{(16)}$ %

\end{document}


• That's a shame : your answer is great and does exactly what I asked for (I just add to replace \clipbox{\boxoffset+0pt 0pt with \clipbox{\boxoffset+0pt -1pt because of numbers bottom was cut). But @egreg answer also includes other features that I did not ask but that I needed. Thanks a lot for your work ! – lauhub Feb 25 '15 at 14:00
• @lauhub Thanks for the kind words. egreg's answer is certainly better than this, but it was what I could contribute. Kind regards. – Steven B. Segletes Feb 25 '15 at 16:47