如何使用 `\bitwiseXor{1}{2}` 之类的命令对数字进行二进制运算并返回结果

如何使用 `\bitwiseXor{1}{2}` 之类的命令对数字进行二进制运算并返回结果

我一直在尝试寻找一种方法来执行\bitwiseXor{1,2}\bitwiseXor{1}{2}并让它返回 3。

  • 我尝试使用 pgfmath,但没有成功(这是在 TikZ 自动生成的图表中使用)
  • 我也尝试过这个bitset包,但没有成功。
  • 我尝试使用pythontex,但它需要更复杂的编译。由于我正在共享此文件,因此我会更喜欢如果编译是一个单步过程。
  • 最后,我看到@egreg 回答了类似的问题这里,所以可以做到,但我不能理解 latex3,也不知道如何把所有东西都取出来,只进行返回十进制(或二进制)数字的操作。

谢谢

答案1

这是一个完全可扩展的按位异或的实现。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\bitwiseXor}{mm}
 {
  \recuenco_bitwise_xor:nn { #1 } { #2 }
 }

\cs_new:Nn \recuenco_bitwise_xor:nn
 {
  \int_from_bin:e
   {
    \__recuenco_bitwise_xor:ee { \int_to_bin:n { #1 } } { \int_to_bin:n { #2 } }
   }
 }
\cs_generate_variant:Nn \int_from_bin:n { e }

\cs_new:Nn \__recuenco_bitwise_xor:nn
 {
  \__recuenco_bitwise_xor_binary:ee
   {
    \prg_replicate:nn
     {
      \int_max:nn { \tl_count:n { #1 } } { \tl_count:n { #2 } } - \tl_count:n { #1 }
     }
     { 0 }
     #1
   }
   {
    \prg_replicate:nn
     {
      \int_max:nn { \tl_count:n { #1 } } { \tl_count:n { #2 } } - \tl_count:n { #2 }
     }
     { 0 }
     #2
   }
 }
\cs_generate_variant:Nn \__recuenco_bitwise_xor:nn { ee }

\cs_new:Nn \__recuenco_bitwise_xor_binary:nn
 {
  \__recuenco_bitwise_xor_binary:w #1;#2;
 }
\cs_generate_variant:Nn \__recuenco_bitwise_xor_binary:nn { ee }

\cs_new:Npn \__recuenco_bitwise_xor_binary:w #1#2;#3#4;
 {
  \int_abs:n { #1-#3 }
  \tl_if_empty:nF { #2 } { \__recuenco_bitwise_xor_binary:w #2;#4; }
 }

\ExplSyntaxOff

\begin{document}

\bitwiseXor{93}{208}

\end{document}

首先将输入转换为二进制。然后通过在较短的数字前填充适当数量的零来使两个数字的长度相等。

然后调用递归宏,通过计算差的绝对值来输出每个位的 XOR。

将结果转换为十进制形式。

您可以检查输出是否为141。


扩展还涵盖 AND 和 OR。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\bitwiseAnd}{mm}
 {
  \recuenco_bitwise:nnN { #1 } { #2 } \__recuenco_bitwise_and_binary:w
 }
\NewExpandableDocumentCommand{\bitwiseOr}{mm}
 {
  \recuenco_bitwise:nnN { #1 } { #2 } \__recuenco_bitwise_or_binary:w
 }
\NewExpandableDocumentCommand{\bitwiseXor}{mm}
 {
  \recuenco_bitwise:nnN { #1 } { #2 } \__recuenco_bitwise_xor_binary:w
 }

\cs_new:Nn \recuenco_bitwise:nnN
 {
  \int_from_bin:e
   {
    \__recuenco_bitwise:eeN { \int_to_bin:n { #1 } } { \int_to_bin:n { #2 } } #3
   }
 }
\cs_generate_variant:Nn \int_from_bin:n { e }

\cs_new:Nn \__recuenco_bitwise:nnN
 {
  \__recuenco_bitwise_binary:eeN
   {
    \prg_replicate:nn
     {
      \int_max:nn { \tl_count:n { #1 } } { \tl_count:n { #2 } } - \tl_count:n { #1 }
     }
     { 0 }
     #1
   }
   {
    \prg_replicate:nn
     {
      \int_max:nn { \tl_count:n { #1 } } { \tl_count:n { #2 } } - \tl_count:n { #2 }
     }
     { 0 }
     #2
   }
   #3
 }
\cs_generate_variant:Nn \__recuenco_bitwise:nnN { ee }

\cs_new:Nn \__recuenco_bitwise_binary:nnN
 {
  #3 #1;#2;
 }
\cs_generate_variant:Nn \__recuenco_bitwise_binary:nnN { ee }

\cs_new:Npn \__recuenco_bitwise_and_binary:w #1#2;#3#4;
 {
  \int_eval:n { #1*#3 }
  \tl_if_empty:nF { #2 } { \__recuenco_bitwise_and_binary:w #2;#4; }
 }
\cs_new:Npn \__recuenco_bitwise_or_binary:w #1#2;#3#4;
 {
  \int_max:nn { #1 } { #3 }
  \tl_if_empty:nF { #2 } { \__recuenco_bitwise_or_binary:w #2;#4; }
 }
\cs_new:Npn \__recuenco_bitwise_xor_binary:w #1#2;#3#4;
 {
  \int_abs:n { #1-#3 }
  \tl_if_empty:nF { #2 } { \__recuenco_bitwise_xor_binary:w #2;#4; }
 }

\cs_new:Npn \bin #1 { \exp_args:Ne \int_to_bin:n { #1 } }

\ExplSyntaxOff

\begin{document}

$93\mathbin{\mathrm{AND}}208=\bitwiseAnd{93}{208}$\quad
\begin{tabular}[t]{r}
\bin{93} \\
\bin{208} \\
\hline
\bin{\bitwiseAnd{93}{208}}
\end{tabular}

\bigskip

$93\mathbin{\mathrm{OR}}208=\bitwiseOr{93}{208}$\quad
\begin{tabular}[t]{r}
\bin{93} \\
\bin{208} \\
\hline
\bin{\bitwiseOr{93}{208}}
\end{tabular}

\bigskip

$93\mathbin{\mathrm{XOR}}208=\bitwiseXor{93}{208}$
\begin{tabular}[t]{r}
\bin{93} \\
\bin{208} \\
\hline
\bin{\bitwiseXor{93}{208}}
\end{tabular}

\end{document}

在此处输入图片描述

答案2

下面3使用bitset包生成结果。Dec宏名称中的 表示我们使用十进制表示法。包中提供了其他表示法 (https://ctan.org/pkg/bitset)。

Set用于Get设置和检索数据。使用逻辑运算符(例如),\bitsetXor结果将放入第一个参数中。

MWE 执行 1 XOR 2 得到 3,将其放入 A 寄存器中。然后执行 3 AND 2 得到结果 2。

\documentclass{article}
\usepackage{bitset}
\begin{document}
\bitsetSetDec{A}{1}
\bitsetSetDec{B}{2}
\bitsetXor{A}{B} 
\bitsetGetDec{A}

\bitsetAnd{A}{B}
\bitsetGetDec{A}
\end{document}

在此处输入图片描述

答案3

如果你愿意使用 LuaLaTeX,这里有个好消息:Lua5.3(LuaTeX 的一部分)具有几个按位运算。摘自 Lua5.3 参考手册第 3.4.2 节:

在此处输入图片描述

唯一稍微有点棘手的事情是找到一种方法将 TeX 特殊字符“偷运”~到 Lua。我知道的最简单的方法是加载luacode包并使用它\luaexec宏。

当然,也可以创建 LaTeX 宏作为 Lua 按位运算的“包装器”。请参阅\bitwiseXOR下面的宏,它接受两个参数。

在此处输入图片描述

\documentclass{article}
\usepackage{luacode} % for '\luaexec' macro
%% Define a LaTeX "wrapper" macro:
\newcommand\bitwiseXOR[2]{\luaexec{tex.sprint((#1)~(#2))}}
\newcommand\bitwiseAND[2]{\luaexec{tex.sprint((#1)&(#2))}}
\newcommand\bitwiseOR[2]{\luaexec{tex.sprint((#1)|(#2))}}

\begin{document}
The output of \verb+\luaexec{tex.sprint(1~2)}+ is \luaexec{tex.sprint(1~2)}.

The output of \verb|\bitwiseXOR{2-1}{1+1}| is also \bitwiseXOR{2-1}{1+1}.
\end{document}

答案4

这是一个仅限 pgf 的解决方案。它只需要 pgf 及其解析器模块。一切都由 pgf 函数完成,这些函数可以在 pgf 中照常使用和解析。

\documentclass{article}
\usepackage{pgf}
\usepgfmodule{parser}
\makeatletter
\pgfparserdef{prp}{initial}{the character 0}% 
{\global\advance\pgfutil@tempcnta by1\relax
\edef\pgf@bit@list{0,\pgf@bit@list}}%
\pgfparserdef{prp}{initial}{the character 1}% 
{\global\advance\pgfutil@tempcnta by1\relax
\edef\pgf@bit@list{1,\pgf@bit@list}}%
\pgfparserdef{prp}{initial}{the character ;}% 
{\pgfparserswitch{final}}%
\pgfmathdeclarefunction{bitand}{2}{\begingroup
\pgfutil@tempcnta0\relax
\edef\pgf@bit@list{}%
\pgfparserparse{prp}#1;%
\pgfutil@tempcntb\pgfutil@tempcnta
\edef\pgfutil@tmpa{\pgf@bit@list}%
\pgfutil@tempcnta0\relax
\edef\pgf@bit@list{}%
\pgfparserparse{prp}#2;%
\edef\pgfutil@tmpb{\pgf@bit@list}%
\ifnum\pgfutil@tempcnta<\pgfutil@tempcntb\relax
\pgfutil@tempcntb\pgfutil@tempcnta
\fi
\pgfutil@tempcnta0\relax
\edef\pgfutil@tmpe{}%
\loop
\pgfmathsetmacro{\pgfutil@tmpc}{{\pgfutil@tmpa}[\pgfutil@tempcnta]}%
\pgfmathsetmacro{\pgfutil@tmpd}{{\pgfutil@tmpb}[\pgfutil@tempcnta]}%
\pgfmathparse{int(and(\pgfutil@tmpc,\pgfutil@tmpd))}%
\edef\pgfutil@tmpe{\pgfmathresult\pgfutil@tmpe}%
\advance\pgfutil@tempcnta1\relax
\ifnum\pgfutil@tempcnta<\pgfutil@tempcntb
\repeat
\edef\pgfmathresult{\pgfutil@tmpe}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\pgfmathdeclarefunction{bitor}{2}{\begingroup
\pgfutil@tempcnta0\relax
\edef\pgf@bit@list{}%
\pgfparserparse{prp}#1;%
\pgfutil@tempcntb\pgfutil@tempcnta
\edef\pgfutil@tmpf{\the\numexpr\pgfutil@tempcnta-1}%
\edef\pgfutil@tmpa{\pgf@bit@list}%
\pgfutil@tempcnta0\relax
\edef\pgf@bit@list{}%
\pgfparserparse{prp}#2;%
\edef\pgfutil@tmpb{\pgf@bit@list}%
\edef\pgfutil@tmpg{\the\numexpr\pgfutil@tempcnta-1}%
\ifnum\pgfutil@tempcnta>\pgfutil@tempcntb\relax
\pgfutil@tempcntb\pgfutil@tempcnta
\fi
\pgfutil@tempcnta0\relax
\edef\pgfutil@tmpe{}%
\loop
\ifnum\pgfutil@tempcnta>\pgfutil@tmpf
\pgfmathsetmacro{\pgfutil@tmpc}{0}%
\else
\pgfmathsetmacro{\pgfutil@tmpc}{{\pgfutil@tmpa}[\pgfutil@tempcnta]}%
\fi
\ifnum\pgfutil@tempcnta>\pgfutil@tmpg
\pgfmathsetmacro{\pgfutil@tmpd}{0}%
\else
\pgfmathsetmacro{\pgfutil@tmpd}{{\pgfutil@tmpb}[\pgfutil@tempcnta]}%
\fi
\pgfmathparse{int(or(\pgfutil@tmpc,\pgfutil@tmpd))}%
\edef\pgfutil@tmpe{\pgfmathresult\pgfutil@tmpe}%
\advance\pgfutil@tempcnta1\relax
\ifnum\pgfutil@tempcnta<\pgfutil@tempcntb
\repeat
\edef\pgfmathresult{\pgfutil@tmpe}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\pgfmathdeclarefunction{bitxor}{2}{\begingroup
\pgfutil@tempcnta0\relax
\edef\pgf@bit@list{}%
\pgfparserparse{prp}#1;%
\pgfutil@tempcntb\pgfutil@tempcnta
\edef\pgfutil@tmpf{\the\numexpr\pgfutil@tempcnta-1}%
\edef\pgfutil@tmpa{\pgf@bit@list}%
\pgfutil@tempcnta0\relax
\edef\pgf@bit@list{}%
\pgfparserparse{prp}#2;%
\edef\pgfutil@tmpb{\pgf@bit@list}%
\edef\pgfutil@tmpg{\the\numexpr\pgfutil@tempcnta-1}%
\ifnum\pgfutil@tempcnta>\pgfutil@tempcntb\relax
\pgfutil@tempcntb\pgfutil@tempcnta
\fi
\pgfutil@tempcnta0\relax
\edef\pgfutil@tmpe{}%
\loop
\ifnum\pgfutil@tempcnta>\pgfutil@tmpf
\pgfmathsetmacro{\pgfutil@tmpc}{0}%
\else
\pgfmathsetmacro{\pgfutil@tmpc}{{\pgfutil@tmpa}[\pgfutil@tempcnta]}%
\fi
\ifnum\pgfutil@tempcnta>\pgfutil@tmpg
\pgfmathsetmacro{\pgfutil@tmpd}{0}%
\else
\pgfmathsetmacro{\pgfutil@tmpd}{{\pgfutil@tmpb}[\pgfutil@tempcnta]}%
\fi
\pgfmathparse{int(mod(\pgfutil@tmpc+\pgfutil@tmpd,2))}%
\edef\pgfutil@tmpe{\pgfmathresult\pgfutil@tmpe}%
\advance\pgfutil@tempcnta1\relax
\ifnum\pgfutil@tempcnta<\pgfutil@tempcntb
\repeat
\edef\pgfmathresult{\pgfutil@tmpe}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\pgfmathdeclarefunction{bitwiseAnd}{2}{\begingroup
\pgfmathsetmacro{\pgfutil@tmpa}{bin(#1)}%
\pgfmathsetmacro{\pgfutil@tmpb}{bin(#2)}%
\pgfmathsetmacro{\pgfutil@tmpc}{bitand("\pgfutil@tmpa","\pgfutil@tmpb")}%
\pgfmathparse{0b\pgfutil@tmpc}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\pgfmathdeclarefunction{bitwiseOr}{2}{\begingroup
\pgfmathsetmacro{\pgfutil@tmpa}{bin(#1)}%
\pgfmathsetmacro{\pgfutil@tmpb}{bin(#2)}%
\pgfmathsetmacro{\pgfutil@tmpc}{bitor("\pgfutil@tmpa","\pgfutil@tmpb")}%
\pgfmathparse{0b\pgfutil@tmpc}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\pgfmathdeclarefunction{bitwiseXor}{2}{\begingroup
\pgfmathsetmacro{\pgfutil@tmpa}{bin(#1)}%
\pgfmathsetmacro{\pgfutil@tmpb}{bin(#2)}%
\pgfmathsetmacro{\pgfutil@tmpc}{bitxor("\pgfutil@tmpa","\pgfutil@tmpb")}%
\pgfmathparse{0b\pgfutil@tmpc}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\makeatother
\begin{document}
$1~\mbox{XOR}~2=\pgfmathparse{bitwiseXor(1,2)}\pgfmathresult$

$3~\mbox{AND}~5=\pgfmathparse{bitwiseAnd(3,5)}\pgfmathresult$

\medskip

\edef\bitA{0100110101}%
\edef\bitB{1010110010001}%
\pgfmathsetmacro{\bitAandB}{bitand("\bitA","\bitB")}%
\pgfmathsetmacro{\bitAorB}{bitor("\bitA","\bitB")}%
\pgfmathsetmacro{\bitAxorB}{bitxor("\bitA","\bitB")}%


\begin{tabular}{c}
\begin{tabular}{lr}
first bit sequence & \bitA \\
second bit sequence & \bitB \\
\hline
first AND second & \bitAandB \\
\end{tabular} \\[2em] 
\begin{tabular}{lr}
first bit sequence & \bitA \\
second bit sequence & \bitB \\
\hline
first OR second & \bitAorB \\
\end{tabular} \\[2em]
\begin{tabular}{lr}
first bit sequence & \bitA \\
second bit sequence & \bitB \\
\hline
first XOR second & \bitAxorB \\
\end{tabular} 
\end{tabular}
\end{document}

在此处输入图片描述

相关内容