作为离散数学作业的一部分,我需要使用有符号的数值、1 的补码和 2 的补码将不同的十进制值(正数和负数)转换为 8 位二进制表示。有人能建议一种优雅的方式来呈现我的解决方案吗?
手写技术的示例如下
答案1
在你最初的问题中,我以为你正在寻找有关制表位模式的方法的建议,类似于前几个示例。但你的编辑表明你想显示工作情况。类似这样的方法可能可以解决这个问题,我只是按照你展示的简单无符号情况进行操作,其余的我留着,因为你说这是家庭作业:-)
\documentclass{article}
\newcommand\decbin[9]{%
\par\smallskip
\makebox[3cm][r]{$#1$\ }\fbox{#2}\,\fbox{#3}\,\fbox{#4}\,\fbox{#5}\,\fbox{#6}\,\fbox{#7}\,\fbox{#8}\,\fbox{#9}\par}
\def\unsignedbytecalc#1{%
\par\smallskip
\noindent$#1_{10}$\par
\smallskip
\gdef\result{}%
$\left.\begin{array}{r@{\quad}|c}\udbc{#1}\end{array}\right\}\result$\par}
\makeatletter
\def\udbc#1{%
\ifnum#1=\z@
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{2)\!\underline{\,#1}&\edef\r{\ifodd#1 1\else 0\fi}\r\xdef\result{\r\result}\\
\expandafter\udbc\expandafter{\the\numexpr(\ifodd#1 #1-1\else#1\fi)/2\relax}%
}}
\begin{document}
\decbin{13} 00001101
\decbin{54} 00110110
\unsignedbytecalc{156}
\end{document}
答案2
更新:我在最后添加了一个 b 进制到十进制转换的逆过程的图示
我还没有尝试过使用向上箭头... 我很抱歉,因为这些操作@
使得代码难以阅读(对我来说)。我最初使用等\n
...\m
但人们总是担心在 LaTeX 中覆盖某些内容。
该方法使用表格内的可扩展循环,以便获得右侧对齐。不对不应为负数的输入进行任何测试。
我对局部和全局赋值做了一些尝试,但也许使用一个计数变量会让代码更易于阅读。无论如何,重点是计算不应重复进行,尽管表格单元格限制了范围。
当基数为 $\leq 36$ 时,数字使用以 $10 = A$ 开头的字母表。
基数是可选参数。请不要使用1
...
\documentclass{article}
\usepackage[left=1cm, right=2cm, vmargin=1cm]{geometry}
% expandable loop (used to avoid scope problems in tabular cells with the
% standard \loop)
\def\boucle #1\repeat {#1\b@@cle {#1}\repeat \repeat }
\def\b@@cle #1{\repeat #1\b@@cle {#1}}
\makeatletter
\newcount\@nn
\newcount\@mm
\newcount\@base
\newcount\@baseminusone
% please do not use this at home
% #1 must be a counter name, not something expanding to a number.
\def\@arabalpha #1{\ifcase #10\or1\or2\or3\or4\or5\or6\or7\or8\or9\or
A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or K\or L\or M\or N\or O\or
P\or Q\or R\or S\or T\or U\or V\or W\or X\or Y\or Z\fi}
\newcommand{\baseexpansion}[2][2]{% no negative numbers please!
\def\@digits{}%
\@base#1\relax \@baseminusone\@base\advance\@baseminusone-1
\@nn #2\relax % this is the number to be written in base #1
%
\ifnum\@baseminusone<36
\def\onerow{#1\kern.1em\hbox{\vrule
\vtop {\hbox{\ \the\@nn}\kern.3ex\hrule height.1ex }} &%
\global\@mm\@nn \global\divide\@mm\@base
\multiply\@mm\@base \advance\@nn-\@mm
\the\@nn \xdef\@digits{\@arabalpha\@nn\@digits}}%
\else
\def\onerow{#1\kern.1em\hbox{\vrule
\vtop {\hbox{\ \the\@nn}\kern.3ex\hrule height.1ex }} &%
\global\@mm\@nn \global\divide\@mm\@base
\multiply\@mm\@base \advance\@nn-\@mm
\the\@nn \xdef\@digits{\the\@nn.\@digits}}%
\fi
%
\leavevmode\oalign{$#2_{10}:$\hfil\cr
$\left.
\begin{tabular}{r|l}
\boucle \onerow \\ \ifnum\@nn>\@baseminusone\global\@nn\@mm \repeat
\end{tabular}\right\rbrace=
\mathtt{\@digits}_{#1}$}} % \hfil removed from the macro
\makeatother
\begin{document}\thispagestyle{empty}
\lineskip12pt
\baseexpansion{1000}\hfil
\baseexpansion[3]{1000}\hfil
\baseexpansion[4]{1000}\hfil
\baseexpansion[5]{1000}\hfil
\baseexpansion[6]{1000}\hfil
\baseexpansion[7]{1000}\hfil
\baseexpansion[8]{1000}\hfil
\baseexpansion[9]{1000}\hfil
\baseexpansion[10]{1000}\hfil
\baseexpansion[11]{1000}\hfil
\baseexpansion[12]{1000}\hfil
\baseexpansion[13]{1000}\hfil
\baseexpansion[14]{1000}\hfil
\baseexpansion[15]{1000}\hfil
\baseexpansion[16]{1000}\hfil
\baseexpansion{1024}\hfil
\baseexpansion[16]{1024}\hfil
\baseexpansion[3]{6561}\hfil
\baseexpansion[111]{1000000}\hfil
\baseexpansion[111]{1000000000}\hfil
\baseexpansion[7]{1000000000}\par
\end{document}
\documentclass{article}
\usepackage[left=1cm, right=2cm, vmargin=1cm]{geometry}
%%%-----------------------------------------------------------------------------
%%% macros to display the computation of a decimal representation of a positive
%%% integer given in base b representation with b at most 36
\makeatletter
\newcount\@nn
\newcount\@mm
\newcount\@base
% globally sets the counter \@mm to the decimal number represented by #1
% which is either a digit 0-9 or a letter A-Z or a-z
% no check on input done!
%\def\@set@mmto #1{\@mm`#1 \advance\@mm-48
% \ifnum\@mm>48 \advance\@mm-39 \else
% \ifnum\@mm>16 \advance\@mm-7 \fi\fi \global\@mm\@mm}
% I had initially:
\def\@set@mmto #1{\@mm`#1
\ifnum\@mm>96 \advance\@mm-87 \else
\ifnum\@mm>64 \advance\@mm-55 \else
\advance\@mm-48 \fi\fi \global\@mm\@mm}
% prepares the first three entries of a row of the future tabular
% \@nn represents the decimal number so far computed, and will
% turn into base times itself plus new digit
% global assignments to transcend cells
\def\@mostofonerow#1{\xdef\@digitssofar{\@digitssofar#1}%
\@set@mmto #1%
$\mathtt{\@digitssofar_{\the@base}}\rightarrow\the\@mm\;$%
&%
${}+\the@base\times\the\@nn$%
\multiply\@nn\@base
\advance\@nn\@mm
\global\@nn\@nn
&${}={}$&}
% this is for displaying the final result in a box
\def\@endfinalrow{\fbox{$\the\@nn_{10}$}\\}
% this is the non-boxed intermediate result ending a row
\def\@endnormalrow{$\the\@nn$\\}
% recursive construction of successive rows
\def\@makenextrows#1{\ifx#1.\@endfinalrow\else
\@endnormalrow\@mostofonerow#1\expandafter\@makenextrows\fi}
% first step for initialization. Checks for empty argument.
\def\@makerows #1{\ifx#1.\else\@mostofonerow#1\expandafter\@makenextrows\fi}
%% actually constructs the tabular with the computation
%% [moved to \todecimal]
%\def\@displayrows #1{{\setlength{\tabcolsep}{0pt}%
% \begin{tabular}[t]{r|lcl}#1\end{tabular}}}
\newcommand{\todecimal}[2][2]{%
\@base=#1\def\the@base{#1}%
\@nn=0
\def\@digitssofar{}%
\oalign{$\mathtt{#2_{#1}}:$\hfil\cr
%%%% replaced
%%%% \expandafter\@displayrows\expandafter{\@makerows #2.}}}
%%%% with the simpler:
{%
\setlength{\tabcolsep}{0pt}%
\begin{tabular}[t]{r|lcl}
\@makerows #2.
\end{tabular}%
}%
}%
} % end ot \todecimal
\makeatother
\begin{document}
\todecimal{0}\medskip
\todecimal{1}\medskip
\todecimal{10101110}\medskip
\todecimal[16]{AE}\medskip
\todecimal[16]{aE}\medskip
\todecimal[7]{351}\medskip
\todecimal[36]{zz}\medskip
\todecimal[36]{xYz}
\end{document}
答案3
不可避免的 LaTeX3 解决方案。
可选参数\decbin
表示位数(默认为 8);\bitcalc
应在数学模式下使用。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% the needed variables
\tl_new:N \l__bee_bindigits_tl
\seq_new:N \l__bee_quotients_seq
\seq_new:N \l__bee_remainders_seq
% the user level macros
\NewDocumentCommand{\decbin}{ O{8} m }
{
\bee_decbin:nn { #1 } { #2 }
}
\NewDocumentCommand{\bitcalc}{m}
{
\bee_bitcalc:n {#1}
}
% the internal functions
\cs_new:Npn \bee_decbin:nn #1 #2
{
\int_compare:nTF { #2 >= 1 \prg_replicate:nn { #1 } { *2 } }
{
BAD! % too few bits
}
{
\bee_print_decbin:nn { #1 } { #2 }
}
}
\cs_new_protected:Npn \bee_print_decbin:nn #1 #2
{
% compute the binary representation
\tl_set:Nx \l__bee_bindigits_tl { \int_to_binary:n { #2 } }
% pad with zeros
\prg_replicate:nn { #1 - \tl_count:N \l__bee_bindigits_tl }
{ \tl_put_left:Nn \l__bee_bindigits_tl { 0 } }
% print the original number
$#2\sb{10}$
% print the boxed binary digits
\tl_map_inline:Nn \l__bee_bindigits_tl { \,\fbox{##1} }
}
\cs_new_protected:Npn \bee_bitcalc:n #1
{
% print the number and start the recursion
#1\sb{10}\to
\seq_clear:N \l__bee_quotients_seq
\seq_clear:N \l__bee_remainders_seq
\bee_bitcalc_aux:n { #1 }
% after the recursion print the binary representation
\int_to_binary:n { #1 }\sb{2}
}
\cs_new_protected:Npn \bee_bitcalc_aux:n #1
{
% if the quotient is nonzero store the current quotient
% and the remainder of the division by 2, then repeat;
% otherwise print the result
\int_compare:nTF { #1 > 0 }
{
\seq_put_right:Nn \l__bee_quotients_seq { 2)\!\underline{\,\, #1 } }
\seq_put_right:Nx \l__bee_remainders_seq { \int_mod:nn { #1 } { 2 } }
\bee_bitcalc_aux:x { \int_div_truncate:nn { #1 } { 2 } }
}
{
\bee_print_computation:
}
}
\cs_generate_variant:Nn \bee_bitcalc_aux:n { x }
\cs_new_protected:Npn \bee_print_computation:
{
\left\{\left.\kern-\nulldelimiterspace
% print the array of quotients
\begin{array}{r}\seq_use:Nnnn \l__bee_quotients_seq { \\ } { \\ } { \\ }\end{array}
\right\uparrow
% print the array of remainders
\begin{array}{c}\seq_use:Nnnn \l__bee_remainders_seq { \\ } { \\ } { \\ }\end{array}
\right\}
}
\ExplSyntaxOff
\begin{document}
\decbin{1}
\decbin{255}
\decbin[16]{256}
\[
\bitcalc{156}
\]
\end{document}
通过直接更改几个宏,我们就可以扩展\bitcalc
它以执行对(几乎)任意基数的转换:
\NewDocumentCommand{\bitcalc}{ O{2} m }
{
\bee_bitcalc:nn { #1 } { #2 }
}
\cs_new_protected:Npn \bee_bitcalc:nn #1 #2
{
% print the number and start the recursion
#2\sb{10}\to
\seq_clear:N \l__bee_quotients_seq
\seq_clear:N \l__bee_remainders_seq
\bee_bitcalc_aux:nn { #1 } { #2 }
% after the recursion print the binary representation
\mathrm{ \int_to_base:nn { #2 } { #1 }\sb{ #1 } }
}
\cs_new_protected:Npn \bee_bitcalc_aux:nn #1 #2
{
% if the quotient is nonzero store the current quotient
% and the remainder of the division by #1, then repeat;
% otherwise print the result. Here #1 is the base.
\int_compare:nTF { #2 > 0 }
{
\seq_put_right:Nn \l__bee_quotients_seq { #1)\!\underline{\,\, #2 } }
\seq_put_right:Nx \l__bee_remainders_seq { \int_mod:nn { #2 } { #1 } }
\bee_bitcalc_aux:nx { #1 } { \int_div_truncate:nn { #2 } { #1 } }
}
{
\bee_print_computation:
}
}
\cs_generate_variant:Nn \bee_bitcalc_aux:nn { nx }
无需更改\bee_print_computation:
。输入
\[
\bitcalc[4]{156}\quad\bitcalc[16]{156}
\]
将产生
该函数\int_to_base:nn
支持从 2 到 36 的基数。
几年后的一些修复
此函数\int_to_binary:n
已被弃用。我添加了一个 * 版本,\bitcalc
将其添加到&
箭头之前,用于对齐。
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
% the needed variables
\tl_new:N \l__bee_bindigits_tl
\seq_new:N \l__bee_quotients_seq
\seq_new:N \l__bee_remainders_seq
% the user level macros
\NewDocumentCommand{\decbin}{ O{8} m }
{
\bee_decbin:nn { #1 } { #2 }
}
\NewDocumentCommand{\bitcalc}{ s O{2} m }
{
\bee_bitcalc:nnn { #2 } { #3 } { \IfBooleanT{#1}{&} }
}
% the internal functions
\cs_new:Npn \bee_decbin:nn #1 #2
{
\int_compare:nTF { #2 >= 1 \prg_replicate:nn { #1 } { *2 } }
{
BAD! % too few bits
}
{
\bee_print_decbin:nn { #1 } { #2 }
}
}
\cs_new_protected:Npn \bee_print_decbin:nn #1 #2
{
% compute the binary representation
\tl_set:Nx \l__bee_bindigits_tl { \int_to_bin:n { #2 } }
% pad with zeros
\prg_replicate:nn { #1 - \tl_count:N \l__bee_bindigits_tl }
{ \tl_put_left:Nn \l__bee_bindigits_tl { 0 } }
% print the original number
$#2\sb{10}$
% print the boxed binary digits
\tl_map_inline:Nn \l__bee_bindigits_tl { \,\fbox{##1} }
}
\cs_new_protected:Npn \bee_bitcalc:nnn #1 #2 #3
{
% print the number and start the recursion
#2\sb{10}#3\to
\seq_clear:N \l__bee_quotients_seq
\seq_clear:N \l__bee_remainders_seq
\bee_bitcalc_aux:nn { #1 } { #2 }
% after the recursion print the binary representation
\mathrm{ \str_upper_case:f { \int_to_base:nn { #2 } { #1 } }\sb{ #1 } }
}
\cs_new_protected:Npn \bee_bitcalc_aux:nn #1 #2
{
% if the quotient is nonzero store the current quotient
% and the remainder of the division by #1, then repeat;
% otherwise print the result. Here #1 is the base.
\int_compare:nTF { #2 > 0 }
{
\seq_put_right:Nn \l__bee_quotients_seq { #1)\!\underline{\,\, #2 } }
\seq_put_right:Nx \l__bee_remainders_seq { \int_mod:nn { #2 } { #1 } }
\bee_bitcalc_aux:nx { #1 } { \int_div_truncate:nn { #2 } { #1 } }
}
{
\bee_print_computation:
}
}
\cs_generate_variant:Nn \bee_bitcalc_aux:nn { nx }
\cs_new_protected:Npn \bee_print_computation:
{
\left\{
% print the array of quotients
\begin{array}{r}\seq_use:Nn \l__bee_quotients_seq { \\ } \end{array}
\middle\uparrow
% print the array of remainders
\begin{array}{c}\seq_use:Nn \l__bee_remainders_seq { \\ } \end{array}
\right\}
}
\ExplSyntaxOff
\begin{document}
\decbin{1}
\decbin{255}
\decbin[16]{256}
\[
\bitcalc{4096}
\]
\begin{align*}
\bitcalc*{156} & \bitcalc*[3]{156} \\
\bitcalc*[8]{5656} & \bitcalc*[16]{5656}
\end{align*}
\end{document}