\pgfmathdectobase 宏 \pgfmathresult 数字索引或按位运算符

\pgfmathdectobase 宏 \pgfmathresult 数字索引或按位运算符

有没有办法访问由\pgfmathdectobase(或\pgfmathresult) 返回的宏的每个数字(二进制​​数)?这对于打印给定集合的幂集的函数很有用(根据 和 之间的数字的二进制表示02^|given set|

我能想到两个版本 1) 将宏转换为数组并循环或 2) 计算宏的大小并循环(\foreach如果有方法可以访问数字)。不幸的是,我在 pgfmanual 中找不到任何相关内容。

另一个可能的解决方案是使用位掩码。tikz 支持类似的东西吗?或者有没有什么包支持?

\pgfmathdectobase如果有办法在 tikz 之外使用它,我也会很高兴使用可以使用结果的任何其他包。谢谢!

答案1

为了逐位检查数字,方案可能是这样的

\def\temp{10111}
\newcount\bitnumber
\def\slowbinary#1{%
  \ifx\relax#1% end
  \else
    \advance\bitnumber by 1
    \ifcase#1\relax\docasezero\or\docaseone\fi
  \expandafter\slowbinary
  \fi}
\def\processbinary#1{\bitnumber=-1 % reset the counter (we will start at 0)
  \expandafter\slowbinary#1\relax}

\def\docasezero{\message{^^JZero seen}}
\def\docaseone{\message{^^JOne seen}}

\processbinary\temp
\processbinary{1010}

如果需要从较低有效位开始,则必须先反转数字。

\makeatletter
\def\processbinaryrev#1{%
  \bitnumber=-1 % reset the counter (we will start at 0)
  \@reverse{#1}%
  \expandafter\slowbinary\@esrever \relax}

\def\@reverse#1{%
  \edef\@temp{#1}%
  \def\@esrever{}%
  \loop\unless\ifx\@temp\@empty
    \edef\@esrever{\expandafter\@car\@temp\@nil\@esrever}%
    \edef\@temp{\expandafter\@cdr\@temp\@nil}%
  \repeat}
\makeatother

\processbinaryrev\temp

有很多用于反转字符串的循环。PGF 可能也有一些。

\temp您可以使用\pgfmathresult或 的第一个参数来代替\pgfmathdectobase

当然,你会给\docasezero和赋予更有意义的操作\docaseone;这些操作可以使用 的值\bitnumber。你可以定义一组宏作为

\def\docasezero{\csname casezero\romannumeral\bitnumber\endcsname}
\def\docaseone{\csname caseone\romannumeral\bitnumber\endcsname}

\def\casezero{What to do when bit 0 is 0}
\def\caseone{What to do when bit 0 is 1}
\def\casezeroi{What to do when bit 1 is 0}
\def\caseonei{What to do when bit 1 is 1}
\def\casezeroii{What to do when bit 2 is 0}
\def\caseoneii{What to do when bit 2 is 1}
...

这是一个完整的例子(我稍微改变了一下编程风格,使用了@LaTeX 内核提供的常量):

\documentclass[a4paper]{article}

\makeatletter
\newcount\@bitnumber

\def\@slowbinary#1{%
  \ifx\relax#1% end
  \else
    \advance\@bitnumber\@ne
    \ifcase#1\relax\do@casezero\or\do@caseone\fi
  \expandafter\@slowbinary
  \fi}

\def\@reverse#1{%
  \edef\@temp{#1}%
  \def\@esrever{}%
  \loop\unless\ifx\@temp\@empty
    \edef\@esrever{\expandafter\@car\@temp\@nil\@esrever}%
    \edef\@temp{\expandafter\@cdr\@temp\@nil}%
  \repeat}

% \def\processbinary#1{\@bitnumber\m@ne
%   \expandafter\@slowbinary#1\relax}

\def\processbinaryrev#1{\@reverse{#1}\@bitnumber=-1
  \expandafter\@slowbinary\@esrever \relax}

\def\do@casezero{\csname casezero\romannumeral\@bitnumber\endcsname\relax}
\def\do@caseone{\csname caseone\romannumeral\@bitnumber\endcsname\relax}

\makeatother

\def\casezero{What to do when bit 0 is 0\par}
\def\caseone{What to do when bit 0 is 1\par}
\def\casezeroi{What to do when bit 1 is 0\par}
\def\caseonei{What to do when bit 1 is 1\par}
\def\casezeroii{What to do when bit 2 is 0\par}
\def\caseoneii{What to do when bit 2 is 1\par}
\def\casezeroiii{What to do when bit 3 is 0\par}
\def\caseoneiii{What to do when bit 3 is 1\par}
\def\casezeroiv{What to do when bit 4 is 0\par}
\def\caseoneiv{What to do when bit 4 is 1\par}
\def\casezerov{What to do when bit 5 is 0\par}
\def\caseonev{What to do when bit 5 is 1\par}

\def\temp{10111}

\begin{document}

\temp

\processbinaryrev\temp

\bigskip

101110

\processbinaryrev{101110}

\end{document}

在此处输入图片描述

答案2

从您关于位掩码的子问题中,我假设您只处理二进制/八进制/十进制/十六进制?如果是这样,我强烈建议使用位集Heiko Oberdiek 编写的包,提供了对数据进行按位操作的所有常见运算符。

相关内容