我一直在尝试寻找一种方法来执行\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}