How can I illustrate decimal to binary conversion?
In your initial question I thought you were looking at suggestions for ways of tabulating the bit patterns, something like the first couple of examples. But your edit indicated you wanted to display the working. Something like this might work for that, I just do the easy unsigned case as you showed, I leave the rest as you say it's homework:-)
\documentclass{article}
\newcommand\decbin[9]{%
\par\smallskip
\makebox[3cm][r]{$#1$\ }\fbox{#2}\,\fbox{#3}\,\fbox{#4}\,\fbox{#5}\,\fbox{#6}\,\fbox{#7}\,\fbox{#8}\,\fbox{#9}\par}
\def\unsignedbytecalc#1{%
\par\smallskip
\noindent$#1_{10}$\par
\smallskip
\gdef\result{}%
$\left.\begin{array}{r@{\quad}|c}\udbc{#1}\end{array}\right\}\result$\par}
\makeatletter
\def\udbc#1{%
\ifnum#1=\z@
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{2)\!\underline{\,#1}&\edef\r{\ifodd#1 1\else 0\fi}\r\xdef\result{\r\result}\\
\expandafter\udbc\expandafter{\the\numexpr(\ifodd#1 #1-1\else#1\fi)/2\relax}%
}}
\begin{document}
\decbin{13} 00001101
\decbin{54} 00110110
\unsignedbytecalc{156}
\end{document}
Update: I add at the end an illustration of the reverse process of base b to decimal conversion
I have not tried to do the upgoing arrow... I am sorry for all those @
which render the code barely readable (to me). I originally used \n
, \m
etc... but one always fears overwriting something in LaTeX.
The method uses an expandable loop inside a tabular, so as to get alignment on the right. No test is done on the input which should not be negative.
I do a little play with local and global assignments but maybe using one more count variable would give a more easily readable code. The point anyhow is that computations should not be done twice, despite the restricted scope due to the tabular cell.
When the base is $\leq 36$, the digits use the alphabet starting with $10 = A$.
The base is the optional argument. Please do not use 1
...
\documentclass{article}
\usepackage[left=1cm, right=2cm, vmargin=1cm]{geometry}
% expandable loop (used to avoid scope problems in tabular cells with the
% standard \loop)
\def\boucle #1\repeat {#1\b@@cle {#1}\repeat \repeat }
\def\b@@cle #1{\repeat #1\b@@cle {#1}}
\makeatletter
\newcount\@nn
\newcount\@mm
\newcount\@base
\newcount\@baseminusone
% please do not use this at home
% #1 must be a counter name, not something expanding to a number.
\def\@arabalpha #1{\ifcase #10\or1\or2\or3\or4\or5\or6\or7\or8\or9\or
A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or K\or L\or M\or N\or O\or
P\or Q\or R\or S\or T\or U\or V\or W\or X\or Y\or Z\fi}
\newcommand{\baseexpansion}[2][2]{% no negative numbers please!
\def\@digits{}%
\@base#1\relax \@baseminusone\@base\advance\@baseminusone-1
\@nn #2\relax % this is the number to be written in base #1
%
\ifnum\@baseminusone<36
\def\onerow{#1\kern.1em\hbox{\vrule
\vtop {\hbox{\ \the\@nn}\kern.3ex\hrule height.1ex }} &%
\global\@mm\@nn \global\divide\@mm\@base
\multiply\@mm\@base \advance\@nn-\@mm
\the\@nn \xdef\@digits{\@arabalpha\@nn\@digits}}%
\else
\def\onerow{#1\kern.1em\hbox{\vrule
\vtop {\hbox{\ \the\@nn}\kern.3ex\hrule height.1ex }} &%
\global\@mm\@nn \global\divide\@mm\@base
\multiply\@mm\@base \advance\@nn-\@mm
\the\@nn \xdef\@digits{\the\@nn.\@digits}}%
\fi
%
\leavevmode\oalign{$#2_{10}:$\hfil\cr
$\left.
\begin{tabular}{r|l}
\boucle \onerow \\ \ifnum\@nn>\@baseminusone\global\@nn\@mm \repeat
\end{tabular}\right\rbrace=
\mathtt{\@digits}_{#1}$}} % \hfil removed from the macro
\makeatother
\begin{document}\thispagestyle{empty}
\lineskip12pt
\baseexpansion{1000}\hfil
\baseexpansion[3]{1000}\hfil
\baseexpansion[4]{1000}\hfil
\baseexpansion[5]{1000}\hfil
\baseexpansion[6]{1000}\hfil
\baseexpansion[7]{1000}\hfil
\baseexpansion[8]{1000}\hfil
\baseexpansion[9]{1000}\hfil
\baseexpansion[10]{1000}\hfil
\baseexpansion[11]{1000}\hfil
\baseexpansion[12]{1000}\hfil
\baseexpansion[13]{1000}\hfil
\baseexpansion[14]{1000}\hfil
\baseexpansion[15]{1000}\hfil
\baseexpansion[16]{1000}\hfil
\baseexpansion{1024}\hfil
\baseexpansion[16]{1024}\hfil
\baseexpansion[3]{6561}\hfil
\baseexpansion[111]{1000000}\hfil
\baseexpansion[111]{1000000000}\hfil
\baseexpansion[7]{1000000000}\par
\end{document}
\documentclass{article}
\usepackage[left=1cm, right=2cm, vmargin=1cm]{geometry}
%%%-----------------------------------------------------------------------------
%%% macros to display the computation of a decimal representation of a positive
%%% integer given in base b representation with b at most 36
\makeatletter
\newcount\@nn
\newcount\@mm
\newcount\@base
% globally sets the counter \@mm to the decimal number represented by #1
% which is either a digit 0-9 or a letter A-Z or a-z
% no check on input done!
%\def\@set@mmto #1{\@mm`#1 \advance\@mm-48
% \ifnum\@mm>48 \advance\@mm-39 \else
% \ifnum\@mm>16 \advance\@mm-7 \fi\fi \global\@mm\@mm}
% I had initially:
\def\@set@mmto #1{\@mm`#1
\ifnum\@mm>96 \advance\@mm-87 \else
\ifnum\@mm>64 \advance\@mm-55 \else
\advance\@mm-48 \fi\fi \global\@mm\@mm}
% prepares the first three entries of a row of the future tabular
% \@nn represents the decimal number so far computed, and will
% turn into base times itself plus new digit
% global assignments to transcend cells
\def\@mostofonerow#1{\xdef\@digitssofar{\@digitssofar#1}%
\@set@mmto #1%
$\mathtt{\@digitssofar_{\the@base}}\rightarrow\the\@mm\;$%
&%
${}+\the@base\times\the\@nn$%
\multiply\@nn\@base
\advance\@nn\@mm
\global\@nn\@nn
&${}={}$&}
% this is for displaying the final result in a box
\def\@endfinalrow{\fbox{$\the\@nn_{10}$}\\}
% this is the non-boxed intermediate result ending a row
\def\@endnormalrow{$\the\@nn$\\}
% recursive construction of successive rows
\def\@makenextrows#1{\ifx#1.\@endfinalrow\else
\@endnormalrow\@mostofonerow#1\expandafter\@makenextrows\fi}
% first step for initialization. Checks for empty argument.
\def\@makerows #1{\ifx#1.\else\@mostofonerow#1\expandafter\@makenextrows\fi}
%% actually constructs the tabular with the computation
%% [moved to \todecimal]
%\def\@displayrows #1{{\setlength{\tabcolsep}{0pt}%
% \begin{tabular}[t]{r|lcl}#1\end{tabular}}}
\newcommand{\todecimal}[2][2]{%
\@base=#1\def\the@base{#1}%
\@nn=0
\def\@digitssofar{}%
\oalign{$\mathtt{#2_{#1}}:$\hfil\cr
%%%% replaced
%%%% \expandafter\@displayrows\expandafter{\@makerows #2.}}}
%%%% with the simpler:
{%
\setlength{\tabcolsep}{0pt}%
\begin{tabular}[t]{r|lcl}
\@makerows #2.
\end{tabular}%
}%
}%
} % end ot \todecimal
\makeatother
\begin{document}
\todecimal{0}\medskip
\todecimal{1}\medskip
\todecimal{10101110}\medskip
\todecimal[16]{AE}\medskip
\todecimal[16]{aE}\medskip
\todecimal[7]{351}\medskip
\todecimal[36]{zz}\medskip
\todecimal[36]{xYz}
\end{document}
The unavoidable LaTeX3 solution.
The optional argument to \decbin
states the number of bits (default 8); \bitcalc
should be used in math mode.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% the needed variables
\tl_new:N \l__bee_bindigits_tl
\seq_new:N \l__bee_quotients_seq
\seq_new:N \l__bee_remainders_seq
% the user level macros
\NewDocumentCommand{\decbin}{ O{8} m }
{
\bee_decbin:nn { #1 } { #2 }
}
\NewDocumentCommand{\bitcalc}{m}
{
\bee_bitcalc:n {#1}
}
% the internal functions
\cs_new:Npn \bee_decbin:nn #1 #2
{
\int_compare:nTF { #2 >= 1 \prg_replicate:nn { #1 } { *2 } }
{
BAD! % too few bits
}
{
\bee_print_decbin:nn { #1 } { #2 }
}
}
\cs_new_protected:Npn \bee_print_decbin:nn #1 #2
{
% compute the binary representation
\tl_set:Nx \l__bee_bindigits_tl { \int_to_binary:n { #2 } }
% pad with zeros
\prg_replicate:nn { #1 - \tl_count:N \l__bee_bindigits_tl }
{ \tl_put_left:Nn \l__bee_bindigits_tl { 0 } }
% print the original number
$#2\sb{10}$
% print the boxed binary digits
\tl_map_inline:Nn \l__bee_bindigits_tl { \,\fbox{##1} }
}
\cs_new_protected:Npn \bee_bitcalc:n #1
{
% print the number and start the recursion
#1\sb{10}\to
\seq_clear:N \l__bee_quotients_seq
\seq_clear:N \l__bee_remainders_seq
\bee_bitcalc_aux:n { #1 }
% after the recursion print the binary representation
\int_to_binary:n { #1 }\sb{2}
}
\cs_new_protected:Npn \bee_bitcalc_aux:n #1
{
% if the quotient is nonzero store the current quotient
% and the remainder of the division by 2, then repeat;
% otherwise print the result
\int_compare:nTF { #1 > 0 }
{
\seq_put_right:Nn \l__bee_quotients_seq { 2)\!\underline{\,\, #1 } }
\seq_put_right:Nx \l__bee_remainders_seq { \int_mod:nn { #1 } { 2 } }
\bee_bitcalc_aux:x { \int_div_truncate:nn { #1 } { 2 } }
}
{
\bee_print_computation:
}
}
\cs_generate_variant:Nn \bee_bitcalc_aux:n { x }
\cs_new_protected:Npn \bee_print_computation:
{
\left\{\left.\kern-\nulldelimiterspace
% print the array of quotients
\begin{array}{r}\seq_use:Nnnn \l__bee_quotients_seq { \\ } { \\ } { \\ }\end{array}
\right\uparrow
% print the array of remainders
\begin{array}{c}\seq_use:Nnnn \l__bee_remainders_seq { \\ } { \\ } { \\ }\end{array}
\right\}
}
\ExplSyntaxOff
\begin{document}
\decbin{1}
\decbin{255}
\decbin[16]{256}
\[
\bitcalc{156}
\]
\end{document}
With a straightforward change to a couple of macros we can extend \bitcalc
to do the transformation to an (almost) arbitrary base:
\NewDocumentCommand{\bitcalc}{ O{2} m }
{
\bee_bitcalc:nn { #1 } { #2 }
}
\cs_new_protected:Npn \bee_bitcalc:nn #1 #2
{
% print the number and start the recursion
#2\sb{10}\to
\seq_clear:N \l__bee_quotients_seq
\seq_clear:N \l__bee_remainders_seq
\bee_bitcalc_aux:nn { #1 } { #2 }
% after the recursion print the binary representation
\mathrm{ \int_to_base:nn { #2 } { #1 }\sb{ #1 } }
}
\cs_new_protected:Npn \bee_bitcalc_aux:nn #1 #2
{
% if the quotient is nonzero store the current quotient
% and the remainder of the division by #1, then repeat;
% otherwise print the result. Here #1 is the base.
\int_compare:nTF { #2 > 0 }
{
\seq_put_right:Nn \l__bee_quotients_seq { #1)\!\underline{\,\, #2 } }
\seq_put_right:Nx \l__bee_remainders_seq { \int_mod:nn { #2 } { #1 } }
\bee_bitcalc_aux:nx { #1 } { \int_div_truncate:nn { #2 } { #1 } }
}
{
\bee_print_computation:
}
}
\cs_generate_variant:Nn \bee_bitcalc_aux:nn { nx }
No change is needed to \bee_print_computation:
. The input
\[
\bitcalc[4]{156}\quad\bitcalc[16]{156}
\]
will generate
The function \int_to_base:nn
supports bases from 2 to 36.
Some fixes after a few years
The function \int_to_binary:n
has been deprecated. I added a *-version of \bitcalc
that adds &
just before the arrow, for use in alignments.
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
% the needed variables
\tl_new:N \l__bee_bindigits_tl
\seq_new:N \l__bee_quotients_seq
\seq_new:N \l__bee_remainders_seq
% the user level macros
\NewDocumentCommand{\decbin}{ O{8} m }
{
\bee_decbin:nn { #1 } { #2 }
}
\NewDocumentCommand{\bitcalc}{ s O{2} m }
{
\bee_bitcalc:nnn { #2 } { #3 } { \IfBooleanT{#1}{&} }
}
% the internal functions
\cs_new:Npn \bee_decbin:nn #1 #2
{
\int_compare:nTF { #2 >= 1 \prg_replicate:nn { #1 } { *2 } }
{
BAD! % too few bits
}
{
\bee_print_decbin:nn { #1 } { #2 }
}
}
\cs_new_protected:Npn \bee_print_decbin:nn #1 #2
{
% compute the binary representation
\tl_set:Nx \l__bee_bindigits_tl { \int_to_bin:n { #2 } }
% pad with zeros
\prg_replicate:nn { #1 - \tl_count:N \l__bee_bindigits_tl }
{ \tl_put_left:Nn \l__bee_bindigits_tl { 0 } }
% print the original number
$#2\sb{10}$
% print the boxed binary digits
\tl_map_inline:Nn \l__bee_bindigits_tl { \,\fbox{##1} }
}
\cs_new_protected:Npn \bee_bitcalc:nnn #1 #2 #3
{
% print the number and start the recursion
#2\sb{10}#3\to
\seq_clear:N \l__bee_quotients_seq
\seq_clear:N \l__bee_remainders_seq
\bee_bitcalc_aux:nn { #1 } { #2 }
% after the recursion print the binary representation
\mathrm{ \str_upper_case:f { \int_to_base:nn { #2 } { #1 } }\sb{ #1 } }
}
\cs_new_protected:Npn \bee_bitcalc_aux:nn #1 #2
{
% if the quotient is nonzero store the current quotient
% and the remainder of the division by #1, then repeat;
% otherwise print the result. Here #1 is the base.
\int_compare:nTF { #2 > 0 }
{
\seq_put_right:Nn \l__bee_quotients_seq { #1)\!\underline{\,\, #2 } }
\seq_put_right:Nx \l__bee_remainders_seq { \int_mod:nn { #2 } { #1 } }
\bee_bitcalc_aux:nx { #1 } { \int_div_truncate:nn { #2 } { #1 } }
}
{
\bee_print_computation:
}
}
\cs_generate_variant:Nn \bee_bitcalc_aux:nn { nx }
\cs_new_protected:Npn \bee_print_computation:
{
\left\{
% print the array of quotients
\begin{array}{r}\seq_use:Nn \l__bee_quotients_seq { \\ } \end{array}
\middle\uparrow
% print the array of remainders
\begin{array}{c}\seq_use:Nn \l__bee_remainders_seq { \\ } \end{array}
\right\}
}
\ExplSyntaxOff
\begin{document}
\decbin{1}
\decbin{255}
\decbin[16]{256}
\[
\bitcalc{4096}
\]
\begin{align*}
\bitcalc*{156} & \bitcalc*[3]{156} \\
\bitcalc*[8]{5656} & \bitcalc*[16]{5656}
\end{align*}
\end{document}