Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

As part of my homework for discrete math I need to convert different decimal values, both positive and negative, to 8-bit binary representations using signed magnitude, 1's complement, and 2's complement. Could anyone suggest an elegant way to present my solutions?

An example of handwritten technique is available this

enter image description here

share|improve this question
2  
I'm not sure it's a TeX question; broading your question might help to know what you are really after. –  c.p. Feb 2 '13 at 0:07
1  
Welcome to TeX.sx! Do you need another visual example of how to present this kind of algorithm or do you actually want to know how to achieve the linked example in (La)TeX? The former is off-topic, for the latter you might specify where you got stuck reproducing the example: The arrows? The matrix-ish presentation? The lines around the decimal numbers? …? –  Qrrbrbirlbel Feb 2 '13 at 0:09
    
Related question: Repeated division - Converting from base 10 to another base –  Ignasi Sep 9 '13 at 7:51

3 Answers 3

up vote 27 down vote accepted

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

enter image description here

\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}
share|improve this answer

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}

enter image description here

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

enter image description here

The function \int_to_base:nn supports bases from 2 to 36.

share|improve this answer

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}

examples

digits

\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}

todecimal

share|improve this answer
    
Be sure to pass a counter name to \@arabalpha or you'll have bad surprises; \ifcase\numexpr#1\relax 0 is safer (but requires e-TeX, of course). –  egreg Feb 2 '13 at 16:58
    
@egreg thanks for pointing this out to people who might visit this page. I was aware of it and the \@arabalpha is only to be used here. –  jfbu Feb 2 '13 at 20:10
    
@egreg or \ifcase #1\zero\or1\or... with \chardef\zero`0 –  jfbu Feb 3 '13 at 11:41
    
Yes, if all you need is to print a 0; you're losing full expandability, of course. –  egreg Feb 3 '13 at 12:12
    
@egreg @JosephWright Some person or software keeps on modifying my code. I read now \newcommand{\baseexpansion}[2][1] where my original file from which I copy-pasted had \newcommand{\baseexpansion}[2][2] and I never never wrote [2][1]. And similarly I already manually reverted \newcommand{\todecimal}[2][4] to my original \newcommand{\todecimal}[2][2]. I don't know what's going on here. Perhaps the [2][1] was there when I already reverted the [2][4]. –  jfbu Feb 3 '13 at 14:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.