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 .

4

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

  • 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? – Xavier ANSIAUX Feb 21 '18 at 16:11
  • 1
    @XavierANSIAUX That's a not really difficult variation, I think. – egreg Feb 21 '18 at 16:12
  • 1
    @XavierANSIAUX Not so easy, after all. – egreg Feb 21 '18 at 17:49
  • I tested your macro, and it works fine! Thanks a lot! – Xavier ANSIAUX Feb 23 '18 at 21:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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