我正在教如何从一个基数转换到另一个基数,但是,我找不到这样的方法:
我对 Tikz 了解不多,我唯一能做的就是画一个上面有几条线的简单正方形,所以我甚至不知道从哪里开始。有什么建议吗?我不介意输入所有数字,我想要做的是让创建线条的过程自动化。
答案1
编辑:这个答案有 3 个版本,第一个版本基于我对上述方法的误解,第二个版本(我希望)是更正确的解释。第三个版本允许最多 36 个基数的转换(但仅限于引擎的数字范围pgfmath
,即 0-16383)。
第一个:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\newcount\total
\newcount\lasttotal
\newcount\targetbase
\def\basetenconversiontable#1#2{%
\begin{tikzpicture}[every node/.style={minimum width=1cm, minimum height=0.5cm}, x=1cm,y=0.5cm]
%
\total=#1%
\targetbase=#2
\def\newnumber{}
%
\pgfmathloop
\ifnum\total<1
\else
%
\ifnum\pgfmathcounter>1
\node at (\pgfmathcounter, -\pgfmathcounter+1) (tmp) {\the\targetbase};
\draw (tmp.north west) |- (tmp.south east);
%
\node at (\pgfmathcounter-1, -\pgfmathcounter) (tmp) {\pgfmathparse{int(\total*\targetbase)}\pgfmathresult};
\draw (tmp.south west) -- (tmp.south east);
%
\pgfmathparse{int(\lasttotal-\total*\targetbase)}%
\let\digit=\pgfmathresult
\node at (\pgfmathcounter-1, -\pgfmathcounter-1) [text=red] {\digit};
\edef\newnumber{\digit\newnumber}
\fi
%
\ifnum\total<\targetbase
\edef\newnumber{\the\total\newnumber}
\node at (\pgfmathcounter, -\pgfmathcounter) [text=red] {\the\total};
\else
\node at (\pgfmathcounter, -\pgfmathcounter) {\the\total};
\fi
\lasttotal=\total
\divide\total by\targetbase
\repeatpgfmathloop
\draw [->] (\pgfmathcounter-1,-\pgfmathcounter-1) -- ++(-0.5,0);
\node [anchor=west] at (1, -\pgfmathcounter-2) {$#1=\newnumber_{\the\targetbase}$};
\end{tikzpicture}
}
\begin{tabular}{c}
\basetenconversiontable{478}{7} \\
\basetenconversiontable{1362}{5} \\
\basetenconversiontable{365}{3} \\
\basetenconversiontable{637}{2}
\end{tabular}
\end{document}
第二个:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\newcount\columntotal
\newcount\nextcolumntotal
\newcount\tmptotal
\newcount\tmptmptotal
\newcount\targetbase
\newcount\digitcount
\def\getonedigit#1#2;{#1}
\def\getndigits#1{%
\begingroup%
\tmptotal=#1
\pgfmathloop%
\ifnum\tmptotal<10%
\else%
\divide\tmptotal by10%
\repeatpgfmathloop%
\pgfmathsmuggle\pgfmathcounter%
\endgroup%
\edef\ndigits{\pgfmathcounter}%
}
\def\baseconversiontable#1#2{%
\begingroup%
\getndigits{#1}%
\pgfmathsetlengthmacro\tablecolumnwidth{\ndigits*width("$4$")}%
\def\convertednumber{}%
\begin{tikzpicture}
\node (base conversion table) {%
\begin{tikzpicture}
[
table node/.style={
text width=\tablecolumnwidth,
inner sep=0pt,
align=right,
minimum height=0.5cm,
minimum width=\tablecolumnwidth+5pt
},
x=\tablecolumnwidth+5pt,
y=0.5cm
]
\targetbase=#2
\dobaseconversiontable{#1}%
\end{tikzpicture}%
};%
\draw [->](base conversion table.south east) -- ++(-0.5,0);
\node [below, anchor=north west] at (base conversion table.south west) {$#1=\convertednumber_{#2}$};
\end{tikzpicture}
\endgroup%
}
\def\dobaseconversiontable#1{%
\columntotal=#1%
\getndigits{\columntotal}%
\tmptotal=#1%
\divide\tmptotal by\targetbase
\nextcolumntotal=\tmptotal
%
\ifnum\columntotal<\targetbase
\node at (0, 0) [table node, red] (@) {$\the\columntotal$};%
\xdef\convertednumber{\the\columntotal\convertednumber}%
\else%
\node at (1, 0) [table node] (@) {$\the\targetbase$};%
\draw (@.north west) |- (@.south east);
%
\getndigits{\tmptotal}%
\digitcount=\ndigits%
%
\node at (0,0) [table node] {$\the\columntotal$};%
\tmptmptotal=\tmptotal
\pgfmathloop
\ifnum\digitcount=0
\else%
\tmptmptotal=\tmptotal
\ifnum\digitcount>0
\tmptmptotal=\expandafter\getonedigit\the\tmptmptotal;
\fi
\pgfmathparse{int(\tmptmptotal*\targetbase*10^(\digitcount-1))}%
\let\remainder=\pgfmathresult
\pgfmathsetcount\columntotal{\columntotal-\remainder}%
\advance\digitcount by-1
\pgfmathsetcount\tmptotal{\tmptotal-\tmptmptotal*(10^\digitcount)}%
\ifnum\columntotal<\targetbase
\node at (0,-\pgfmathcounter*2) [table node, red] (@) {$\the\columntotal$};%
\xdef\convertednumber{\the\columntotal\convertednumber}%
\digitcount=0%
\else
\node at (0,-\pgfmathcounter*2) [table node](@) {$\the\columntotal$};%
\fi
\draw (@.north west) -- (@.north east);
\node at (0,-\pgfmathcounter*2+1) [table node] {$\remainder$};%
\repeatpgfmathloop%
\tikzset{shift={(1,-1)}}%
\expandafter\dobaseconversiontable\expandafter{\the\nextcolumntotal}%
\fi
}%
\begin{tabular}{c}
\baseconversiontable{478}{7}\\
\baseconversiontable{1366}{5}\\
\baseconversiontable{365}{3}\\
\baseconversiontable{711}{2}
\end{tabular}
\end{document}
第三个版本。思考它工作正常。无论如何,它都有点笨拙。
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\newcount\columntotal
\newcount\nextcolumntotal
\newcount\tmptotal
\newcount\tmptmptotal
\newcount\targetbase
\newcount\digitcount
\def\digittoalpha#1{%
\ifcase#1\relax0\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 p\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z\else?\fi%
}
\def\getonedigit#1#2;{#1}
\def\getndigits#1{%
\begingroup%
\tmptotal=#1
\pgfmathloop%
\ifnum\tmptotal<10%
\else%
\divide\tmptotal by10%
\repeatpgfmathloop%
\pgfmathsmuggle\pgfmathcounter%
\endgroup%
\edef\ndigits{\pgfmathcounter}%
}
\def\baseconversiontable#1#2{%
\begingroup%
\getndigits{#1}%
\pgfmathsetlengthmacro\tablecolumnwidth{\ndigits*width("$4$")}%
\gdef\convertednumber{}%
\begin{tikzpicture}
\node (base conversion table) {%
\begin{tikzpicture}
[
table node/.style={
anchor=north,
text width=\tablecolumnwidth,
inner sep=0pt,
align=right,
minimum height=0.5cm,
minimum width=\tablecolumnwidth+5pt
},
x=\tablecolumnwidth+5pt,
y=0.5cm
]
\targetbase=#2
\dobaseconversiontable{#1}%
\end{tikzpicture}%
};%
\draw [->](base conversion table.south east) -- ++(-0.5,0);
\node [below, anchor=north west] at (base conversion table.south west) {$#1=\convertednumber_{#2}$};
\end{tikzpicture}
\endgroup%
}
\def\dobaseconversiontable#1{%
\columntotal=#1%
\getndigits{\columntotal}%
\tmptotal=#1%
\divide\tmptotal by\targetbase
\nextcolumntotal=\tmptotal
%
\ifnum\columntotal<\targetbase
\edef\currentdigit{\uppercase{\digittoalpha{\the\columntotal}}}%
\ifnum\columntotal>9
\edef\currentdigit{\noexpand\rm{\currentdigit}}%
\fi
\node at (0, 0) [table node] (@) {%
\\% For some reason necessary.
\ifnum\the\columntotal<10
\color{red}$\the\columntotal$%
\else
$\the\columntotal$\\%
\tikz\draw[->](0,0)(-0.75ex,0)--++(0,-0.5);\\%
\color{red}\currentdigit%
\fi
};%
\expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\convertednumber%
\expandafter\expandafter\expandafter{\expandafter\currentdigit\convertednumber}%
\else%
\node at (1, 0) [table node] (@) {$\the\targetbase$};%
\draw (@.north west) |- (@.south east);
%
\getndigits{\tmptotal}%
\digitcount=\ndigits%
%
\node at (0,0) [table node] {$\the\columntotal$};%
\tmptmptotal=\tmptotal
\pgfmathloop
\ifnum\digitcount=0
\else%
\tmptmptotal=\tmptotal
\ifnum\digitcount>0
\tmptmptotal=\expandafter\getonedigit\the\tmptmptotal;
\fi
\pgfmathparse{int(\tmptmptotal*\targetbase*10^(\digitcount-1))}%
% Hmm this is a kludge.
\ifnum\pgfmathresult>\columntotal%
\pgfmathparse{int(\pgfmathresult/10)}%
\fi%
\let\remainder=\pgfmathresult%
\pgfmathsetcount\columntotal{\columntotal-\remainder}%
\advance\digitcount by-1
\pgfmathsetcount\tmptotal{\tmptotal-\tmptmptotal*(10^\digitcount)}%
\ifnum\columntotal<\targetbase
\edef\currentdigit{\uppercase{\digittoalpha{\the\columntotal}}}%
\ifnum\columntotal>9
\edef\currentdigit{\noexpand\rm{\currentdigit}}%
\fi
\node at (0,-\pgfmathcounter*2) [table node] (@) {%
\\
\ifnum\columntotal<10
\color{red}$\the\columntotal$%
\else
$\the\columntotal$\\%
\tikz\draw[->](0,0)(-0.75ex,0)--++(0,-0.5);\\%
\color{red}\currentdigit%
\fi
};%
\expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\convertednumber%
\expandafter\expandafter\expandafter{\expandafter\currentdigit\convertednumber}%
\digitcount=0%
\else
\node at (0,-\pgfmathcounter*2) [table node](@) {$\the\columntotal$};%
\fi
\draw (@.north west) -- (@.north east);
\node at (0,-\pgfmathcounter*2+1) [table node] {$\remainder$};%
\repeatpgfmathloop%
\tikzset{shift={(1,-1)}}%
\expandafter\dobaseconversiontable\expandafter{\the\nextcolumntotal}%
\fi
}%
\begin{tabular}{ccc}
\baseconversiontable{3022}{16}&&
\baseconversiontable{1462}{12}\\
\baseconversiontable{5407}{19}&&
\baseconversiontable{3887}{36}
\end{tabular}
\end{document}
答案2
即使没有 TikZ,使用标准环境也可以做得很好array
:
\documentclass[10pt,letterpaper]{amsart}
\usepackage{xcolor}
\newcommand\myrule[1]{\multicolumn{1}{c|}{#1}}
\newcommand\myred[1]{\textcolor{red}{#1}}
\begin{document}
\begin{gather*}
\begin{array}{*{7}c}
4 & 7 & \myrule{8} & 7 \\
\cline{4-5}
4 & 2 & & 6 & \myrule{8} & 7 \\
\cline{6-6}
& 5 & 8 & 6 & 3 & \myrule{9} & 7 \\
\cline{4-5}\cline{7-7}
& 5 & 6 & & \myred{5} & 7 & \myred{1} \\
\cline{2-3}\cline{6-6}
& & \myred{2} & & & \myred{2}
\end{array} \\
\longleftarrow \\
478 = 1252_{7}
\end{gather*}
\end{document}
后 奎伯比尔贝尔的建议来改变数字之间的间距,可以得到:
\documentclass[10pt,letterpaper]{amsart}
\usepackage{xcolor}
\newcommand\myrule[1]{\multicolumn{1}{@{}c|}{#1}}
\newcommand\myred[1]{\textcolor{red}{#1}}
\begin{document}
\begin{gather*}
\begin{array}{c@{\,}c@{\,}cc@{\,}ccc}
4 & 7 & \myrule{8} & 7 \\
\cline{4-5}
4 & 2 & & 6 & \myrule{8} & 7 \\
\cline{6-6}
& 5 & 8 & 6 & 3 & \multicolumn{1}{c|}{9} & 7 \\
\cline{4-5}\cline{7-7}
& 5 & 6 & & \myred{5} & 7 & \myred{1} \\
\cline{2-3}\cline{6-6}
& & \myred{2} & & & \myred{2}
\end{array} \\
\longleftarrow \\
478 = 1252_{7}
\end{gather*}
\end{document}
TikZ 解决方案:
\documentclass[10pt,letterpaper]{amsart}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
\begin{tikzpicture}
\matrix[matrix of nodes,column sep=-5.5pt,nodes in empty cells] (mat)
{
4 & 7 & 8 & [7pt]7 & & [7pt] \\
4 & 2 & & 6 & 8 & 7 & [7pt]{} \\
& 5 & 8 & 6 & 3 & 9 & 7 \\
& 5 & 6 & & |[red]|5 & 7 & |[red]|1 \\
& & |[red]|2 & & & |[red]|2 \\
};
\draw ([xshift=-1.5pt,yshift=-2pt]mat-1-4.north west) |- ([xshift=-3.5pt]mat-1-6.south west) |- ([xshift=-3.5pt]mat-2-7.south west) |- (mat-3-7.south east);
\draw (mat-4-2.south west) -- (mat-4-3.south east);
\draw (mat-3-4.south west) -- (mat-3-5.south east);
\draw (mat-4-6.south west) -- (mat-4-6.south east);
\node at ([yshift=-10pt]current bounding box.south)
{$\longleftarrow$};
\node at ([yshift=-10pt]current bounding box.south)
{$478=1252_{7}$};
\end{tikzpicture}
\end{document}
在一条评论中,要求对前七个进行特殊对齐:
\documentclass[10pt,letterpaper]{amsart}
\usepackage{xcolor}
\newcommand\myrule[1]{\multicolumn{1}{@{}c|}{#1}}
\newcommand\myred[1]{\textcolor{red}{#1}}
\begin{document}
\begin{gather*}
\begin{array}{c@{\,}c@{\,}cc@{\,}ccc}
4 & 7 & \myrule{8} & \multicolumn{2}{c}{7} \\
\cline{4-5}
4 & 2 & & 6 & \myrule{8} & 7 \\
\cline{6-6}
& 5 & 8 & 6 & 3 & \multicolumn{1}{c|}{9} & 7 \\
\cline{4-5}\cline{7-7}
& 5 & 6 & & \myred{5} & 7 & \myred{1} \\
\cline{2-3}\cline{6-6}
& & \myred{2} & & & \myred{2}
\end{array} \\
\longleftarrow \\
478 = 1252_{7}
\end{gather*}
\end{document}
答案3
另一个TiKZ
解决方案。代码由杰利迪亚兹在塞万提斯,(西班牙 TeX 组)邮件列表。
每个连续的分区都绘制了matrix of nodes
与前一个分区的相对位置。它还标记了每个提醒,以帮助在它们之间划线或放置其他信息。
它不显示完整的除法,只显示被除数、除数和余数。商是下一个除法被除数。
\documentclass[tikz]{standalone}
\usetikzlibrary{matrix,positioning}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Macros for ``successive divisions''
%
\def\Division#1#2#3{ % Dividend, divisor, remainder
\matrix (D) [matrix of nodes,
below=0pt of D-1-2.south east,
row sep=1pt, column sep=1pt,
every node/.append style={minimum width=12mm}] {
#1 \pgfmatrixnextcell #2 \\
|[marcar] (R#1)| #3 \\
};
\draw[shorten >=2pt, shorten <=2pt]
(D-1-2.north west) |- (D-1-2.south east);
}
\def\FinDivision#1{
\node[marcar, below=2pt of D-1-2.south] (C)(C) {#1};
}
\tikzset{marcar/.style={circle,draw,inner sep=2pt,minimum width=0pt,
fill=yellow!10}}
\begin{document}
\begin{tikzpicture}
\coordinate (D-1-2) at (0,0) {}; % We must start with this command.
\Division{25}{2}{1} % First dividend, divisor, remainder
\Division{12}{2}{0} % Dividend (previous quotient), divisor, remainder
\Division{6}{2}{0}
\Division{3}{2}{1}
\FinDivision{1} % Last remainder.
% We can draw an arrow jumping from one remainder
% to the next one. Every reminder is a node called
% Rdividend. Last remainder is node C.
\draw[shorten <=1mm, ->, dashed] (C) to[out=-150,in=-65] (R3);
\draw[shorten <=1mm, ->, dashed] (R3) to[out=-150,in=-65] (R6);
\draw[shorten <=1mm, ->, dashed] (R6) to[out=-150,in=-65] (R12);
\draw[shorten <=1mm, ->, dashed] (R12) to[out=-150,in=-65] (R25);
% Some more information:
\node (MSB) at ([yshift=-1.3cm]R6.south) {Most significant bit (MSB)};
\node (LSB) at ([yshift=-2mm]MSB.south) {Less significant bit (LSB)};
\draw[ ->] (MSB.east) to[out=30,in=-55] (C);
\draw[ ->] (LSB.west) to[out=150,in=-95] (R25);
\end{tikzpicture}
\end{document}