将十六进制数解析为二进制并进行位迭代

将十六进制数解析为二进制并进行位迭代

我目前正在开发一款图形显示软件,因此出于文档目的,我在 TikZ 中重新创建了它:

显示屏图像

我目前使用它来设置显示屏上的各个像素:

\setpixel{x}{y}

其中xy是0至132/64之间的坐标。

实际显示分为 8 页,每页高 8 个像素,发送到显示器的一个字节显示为一列。参见这个图片了解详情。

因为我不想总是计算单个像素,所以我希望 LaTeX 变体能够像真实显示一样运行,也就是说,我想要一些命令,比如

\dispbyte{0x01}
\dispbyte{0x03}
\dispbyte{0x07}
\dispbyte{0x0F}
\dispbyte{0x1F}
\dispbyte{0x3F}
\dispbyte{0x7F}
\dispbyte{0xFF}

(这将创建上面的一个三角形)我有一个想法,我将如何实现当前列和页面切换的计数以及所有这些 - 毕竟对于一些计数器来说这并不难 - 但我只是找不到如何解析十六进制值,然后对它们里面的每一位进行迭代。

我发现计数二进制文件,但它们只以另一种格式显示 LaTeX 计数器,我完全看不懂它们的代码。

完成的源代码(display.sty)和一些示例现已发布在http://cmpl.cc/downloads/disp/

答案1

以下内容从视觉角度来看不如其他答案那么令人印象深刻(马克,我喜欢你的答案!),但解决了 OP 的实际问题:对十六进制值进行按位迭代,当使用bitset包裹作者:Heiko Oberdiek:

\documentclass{article}
\usepackage{bitset}
\usepackage{pgf,pgffor}

\begin{document}

  \bitsetSetHex{mybitset}{AA}
  % use \bitsetGetSetBitList
  % expand first
  \edef\mybits{\bitsetGetSetBitList{mybitset}}
  \noindent
  \foreach \bit in \mybits {%
    Bit \bit{} is set! \\ 
  }

  % just itereate all bits
  \noindent
  \foreach \i in {0,...,7} {%
    Bit \i: \bitsetGet{mybitset}{\i} \\
  }

\end{document}

在此处输入图片描述

答案2

不确定这是否强大,它仅在 PGFMath 有限的数值范围内起作用,而且显然我追求的东西比要求更夸张。

编辑:按照 Daniels 的bitset软件包示例,代码已经更新得更像那样。

\documentclass[border=5pt]{standalone}
\usepackage{tikz}

\newcount\bitcount
\tikzset{
    zeros/.style={
        draw=black,
        insert path={
            (-\nbit-1/2, -1/2) rectangle ++(1,1)
        }
    },
    ones/.style={
        draw=black,
        fill=gray,
        insert path={
            (-\nbit-1/2, -1/2) rectangle ++(1,1)
        }
    },
    max bits/.store in=\maxbits,
    max bits=0
}

\newcommand\dispbyte[2][]{%
    \begingroup%
        \tikzset{#1}%
        \pgfmathsetcount\bitcount{#2}%
        \pgfmathparse{int(\maxbits)}\let\maxbits=\pgfmathresult%
        \pgfmathloop%
        \ifnum\bitcount>0\relax%
            \ifodd\bitcount%
                \expandafter\def\csname bit\pgfmathcounter\endcsname{1}%
            \else%
                \expandafter\let\csname 
                bit\pgfmathcounter\endcsname=\relax%
            \fi%
            \divide\bitcount by2\relax%
        \repeatpgfmathloop%
        \pgfmathparse{int(\maxbits>\pgfmathcounter?\maxbits+1:\pgfmathcounter+1)}%
        \let\nbits=\pgfmathresult%
        \pgfmathloop%
        \ifnum\pgfmathcounter=\nbits\relax%
        \else%
            \let\nbit=\pgfmathcounter%
            \expandafter\ifx\csname bit\pgfmathcounter\endcsname\relax%
                \path [zeros];
            \else%
                \path [ones];
            \fi%
        \repeatpgfmathloop%
    \endgroup%
}

\begin{document}


\begin{tikzpicture}[x=10pt, y=10pt]

\foreach \d [count=\c from 0, evaluate={\x=floor(\c/8)*8; \y=-mod(\c,8);}] 
in 
{%
    0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x1c, 
    0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x1c,
    0x08,0x08,0x10,0x12,0x14,0x28,0x24,0x22,
    0x7f,0x02,0x04,0x08,0x08,0x10,0x20,0x7f}{
    \dispbyte[max bits=8,shift={(\x,\y)}]{\d}
}

\foreach \d [count=\c from 0, evaluate={\x=floor(\c/8)*8; \y=-mod(\c,8);}] 
in 
{%
    0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x1c, 
    0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x1c,
    0x08,0x08,0x10,0x12,0x14,0x28,0x24,0x22,
    0x7f,0x02,0x04,0x08,0x08,0x10,0x20,0x7f}{
    \dispbyte[zeros/.style={},
        ones/.style={
            fill=gray,
            insert path={
                (-\nbit-3/8, -3/8) rectangle ++(0.75,0.75)
            }
        },shift={(\x,\y-9)}]{\d}
}

\foreach \d [count=\c from 0, evaluate={\x=floor(\c/8)*8; \y=-mod(\c,8);}] 
in 
{%
    0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x1c, 
    0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x1c,
    0x08,0x08,0x10,0x12,0x14,0x28,0x24,0x22,
    0x7f,0x02,0x04,0x08,0x08,0x10,0x20,0x7f}{
    \dispbyte[max bits=8,
        zeros/.style={ 
            fill=black,
            insert path={ 
                (-\nbit, 0) circle [radius=0.5]
            }
        },
        ones/.style={
            fill=orange,
            insert path={ 
                (-\nbit, 0) circle [radius=0.5]
            }
        },shift={(\x,\y-18)}]{\d}
}

\end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

您可以使用具有将整数转换为二进制功能的 LaTeX3。而不是\fbox使用您喜欢的宏。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\dispbyte}{m}
 {
  \compiler_dispbyte:n { #1 }
 }

\tl_new:N \l_compiler_bits_tl
\tl_new:N \l_compiler_byte_tl
\cs_new_protected:Npn \compiler_dispbyte:n #1
 {
  % we need to remove the 0x
  \tl_set:Nn \l_compiler_byte_tl { #1 }
  \tl_remove_once:Nn \l_compiler_byte_tl { 0x }
  % convert the number to a string of bits
  \tl_set:Nx \l_compiler_bits_tl
   { \int_to_binary:n { "\l_compiler_byte_tl } }
  % loop through the list of bits
  \tl_map_inline:Nn \l_compiler_bits_tl
   { \fbox{ ##1 } }
 }
\ExplSyntaxOff

\begin{document}
\dispbyte{0x01}

\dispbyte{0x03}

\dispbyte{0x07}

\dispbyte{0x0F}

\dispbyte{0x11}

\dispbyte{0x13}

\dispbyte{0x17}

\dispbyte{0x1F}
\end{document}

如果您需要按相反顺序排列这些位,只需添加

  \tl_set:Nx \l_compiler_bits_tl
   { \tl_reverse:V \l_compiler_bits_tl }

在该\tl_map_inline:Nn线之前。

在此处输入图片描述

答案4

在此处输入图片描述

这将循环遍历十六进制中的二进制数字,为了进行测试,它只是将它们打印出来(以相反的顺序保持代码简单)

\documentclass{article}

\makeatletter
\def\dispbyte#1{\@displaybyte#1\relax}
\def\@displaybyte#1x#2\relax{\count@\string"#2\relax
\loop
  \fbox{\ifodd\count@ 1\else0\fi}%
\divide\count@\tw@
\ifnum\count@>\z@
\repeat}
\makeatother

\begin{document}

\dispbyte{0x17}

\end{document}

相关内容