3

For my students, I'd like a macro to show logical calculations bit by bit ( AND, OR, XOR ) between two numbers in base b ( b integer from 2 to 36) .

Parameters would be number1, number2 and b; number1, number2 are written in base b; The macro translate number1 and number2 in binary, then presents the calculus as shown in pictures below:

pic7 pic8 pic9

Has anyone made this?

Xavier .

1 Answer 1

5

Quite fun to program. :-)

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

\ExplSyntaxOn
\NewDocumentCommand{\showbitwiseand}{mm}
 {
  \bitwise_show:Nnnn \bitwise_and:nnn { #1 } { #2 } { AND }
 }
\NewDocumentCommand{\showbitwiseor}{mm}
 {
  \bitwise_show:Nnnn \bitwise_or:nnn { #1 } { #2 } { OR }
 }
\NewDocumentCommand{\showbitwisexor}{mm}
 {
  \bitwise_show:Nnnn \bitwise_xor:nnn { #1 } { #2 } { XOR }
 }

\NewDocumentCommand{\bitwiseand}{mm}
 {
  \bitwise_compute:Nnnn \bitwise_and:nnn { #1 } { #2 } { AND }
 }
\NewDocumentCommand{\bitwiseor}{mm}
 {
  \bitwise_compute:Nnnn \bitwise_or:nnn { #1 } { #2 } { OR }
 }
\NewDocumentCommand{\bitwisexor}{mm}
 {
  \bitwise_compute:Nnnn \bitwise_xor:nnn { #1 } { #2 } { XOR }
 }

\cs_new_protected:Nn \bitwise_show:Nnnn
 {
  \ensuremath
   {
    #1 { #2 } { #3 } { 0 }
    \begin{array}{r@{}l}
    \lbrack\int_to_bin:n { #2 }\rbrack & \sb{2} \\
    \mathrm{#4}\quad
    \lbrack\int_to_bin:n { #3 }\rbrack & \sb{2} \\
    \midrule
    \lbrack\l__bitwise_out_tl\rbrack & \sb{2} \\
    \multicolumn{2}{l}{#2 \mathbin{\mathrm{#4}} #3 = \l__bitwise_decimal_tl}
    \end{array}
   }
 }

\cs_new_protected:Nn \bitwise_compute:Nnnn
 {
  #2 \mathbin{\mathrm{#4}} #3 = #1 { #2 } { #3 } { 1 }
 }

\tl_new:N \l__bitwise_first_tl
\tl_new:N \l__bitwise_second_tl
\tl_new:N \l__bitwise_out_tl
\tl_new:N \l__bitwise_decimal_tl
\int_new:N \l__bitwise_log_int

\cs_new_protected:Nn \bitwise_and:nnn
 {
  \__bitwise_set:nn { #1 } { #2 }
  \__bitwise_generic:N \__bitwise_and:n
  \__bitwise_normalize:
  \int_compare:nF { #3 = 0 } { \l__bitwise_decimal_tl }
 }
\cs_new_protected:Nn \bitwise_or:nnn
 {
  \__bitwise_set:nn { #1 } { #2 }
  \__bitwise_generic:N \__bitwise_or:n
  \__bitwise_normalize:
  \int_compare:nF { #3 = 0 } { \l__bitwise_decimal_tl }
 }
\cs_new_protected:Nn \bitwise_xor:nnn
 {
  \__bitwise_set:nn { #1 } { #2 }
  \__bitwise_generic:N \__bitwise_xor:n
  \__bitwise_normalize:
  \int_compare:nF { #3 = 0 } { \l__bitwise_decimal_tl }
 }

\cs_new_protected:Nn \__bitwise_generic:N
 {
  \int_step_function:nnnN { 1 } { 1 } { \l__bitwise_log_int } #1
 }

\cs_new_protected:Npn \__bitwise_normalize:
 {
  \tl_reverse:N \l__bitwise_out_tl
  \tl_set:Nx \l__bitwise_decimal_tl { \int_from_bin:V \l__bitwise_out_tl }
  \tl_set:Nx \l__bitwise_out_tl { \int_to_bin:V \l__bitwise_decimal_tl }
 }
\cs_generate_variant:Nn \int_to_bin:n { V }
\cs_generate_variant:Nn \int_from_bin:n { V }

\cs_new_protected:Nn \__bitwise_and:n
 {
  \tl_put_right:Nx \l__bitwise_out_tl
   {
    \int_eval:n
     {
      \tl_item:Nn \l__bitwise_first_tl { #1 }
      *
      \tl_item:Nn \l__bitwise_second_tl { #1 }
     }
   }
 }

\cs_new_protected:Nn \__bitwise_or:n
 {
  \tl_put_right:Nx \l__bitwise_out_tl
   {
    \int_eval:n
     {
      \int_min:nn { 1 }
       {
        \tl_item:Nn \l__bitwise_first_tl { #1 }
        +
        \tl_item:Nn \l__bitwise_second_tl { #1 }
       }
     }
   }
 }

\cs_new_protected:Nn \__bitwise_xor:n
 {
  \tl_put_right:Nx \l__bitwise_out_tl
   {
    \int_eval:n
     {
      \int_if_odd:nTF
       {
        \tl_item:Nn \l__bitwise_first_tl { #1 }
        +
        \tl_item:Nn \l__bitwise_second_tl { #1 }
       }
       { 1 } { 0 }
     }
   }
 }

\cs_new_protected:Nn \__bitwise_set:nn
 {
  \tl_clear:N \l__bitwise_out_tl
  % make the binary representations
  \tl_set:Nx \l__bitwise_first_tl { \int_to_bin:n { #1 } }
  \tl_set:Nx \l__bitwise_second_tl { \int_to_bin:n { #2 } }
  % reverse the token lists
  \tl_reverse:N \l__bitwise_first_tl
  \tl_reverse:N \l__bitwise_second_tl
  % make them equal length
  \int_compare:nNnTF { \tl_count:N \l__bitwise_first_tl } > { \tl_count:N \l__bitwise_second_tl }
   {
    \tl_put_right:Nx \l__bitwise_second_tl
     {
      \prg_replicate:nn { \tl_count:N \l__bitwise_first_tl - \tl_count:N \l__bitwise_second_tl } { 0 }
     }
   }
   {
    \tl_put_right:Nx \l__bitwise_first_tl
     {
      \prg_replicate:nn { \tl_count:N \l__bitwise_second_tl - \tl_count:N \l__bitwise_first_tl } { 0 }
     }
   }
  \int_set:Nn \l__bitwise_log_int { \tl_count:N \l__bitwise_first_tl }
 }
\ExplSyntaxOff

\begin{document}

\[
\showbitwiseand{93}{208}
\qquad
\showbitwiseor{93}{208}
\qquad
\showbitwisexor{93}{208}
\]

In line:
\begin{itemize}
\item $\bitwiseand{93}{208}$
\item $\bitwiseor{93}{208}$
\item $\bitwisexor{93}{208}$
\end{itemize}

\end{document}

enter image description here

4
  • Very fun! Thanks a lot! And if I want EB6 AND 48A ( with entry in base 16 )? Or if I want XYZ4 OR 48AT in base 36? Does it work? Feb 21, 2018 at 16:11
  • 1
    @XavierANSIAUX That's a not really difficult variation, I think.
    – egreg
    Feb 21, 2018 at 16:12
  • 1
    @XavierANSIAUX Not so easy, after all.
    – egreg
    Feb 21, 2018 at 17:49
  • I tested your macro, and it works fine! Thanks a lot! Feb 23, 2018 at 21:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .