我正在尝试使用 TikZ 结合 pythontex 和 cancel 包来绘制有理数平面(的剪辑),其中所有 gcd 不等于 1 的有理数都被划掉。
这是我的代码迄今为止:
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{pythontex}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{pycode}
def ggt(a,b):
r=a%b
i=0
erg=1
while r:
a=b
b=r
r=a%b
return b
\end{pycode}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\ifnum\py{ggt(\m,\n)}=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi
}
\end{tikzpicture}
\end{document}
问题:“!缺失数字,视为零。“我认为,这是在\ifnum
语句中引起的,在该语句中我调用了\py{ggt(\m,\n)}
,但显然它没有被视为数字。
我的问题:有没有办法让 LaTeX 将我的 python 方法的返回值读取为“数字”?或者有没有完全不使用 pythontex 的方法?任何帮助都非常感谢!另外,我对 LaTeX 还很陌生,所以如果我犯了任何明显或愚蠢的错误,我深表歉意。
答案1
由于您还要求提供替代方法:
您已经使用了tikz
能够进行大量数学计算的包。因此,您只需使用 PGF 函数即可gcd()
。您可以使用 调用相关计算\pgfmathparse{gcd(\m,\n)}
,然后将结果存储在名为 的宏中,\pgfmathresult
您可以在子句中使用该宏\if
:
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\pgfmathparse{gcd(\m,\n)}
\ifnum\pgfmathresult=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi
}
\end{tikzpicture}
\end{document}
还有一个名为的包calculator
,它提供了一个宏\GCD
,允许您动态计算最大公约数并将其存储在单独的宏中,然后您可以在子句中使用它\if
,如下所示:
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{calculator}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\GCD{\m}{\n}{\thisgcd}
\ifnum\thisgcd=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi
}
\end{tikzpicture}
\end{document}
另外,你也可以用 Lua 来执行这样的计算。我找到了一个用 Lua 计算最大公约数的脚本在这个很好的答案中。请注意,您需要使用 LuaLaTeX 而不是 PDFLaTeX 来编译您的文档才能使其正常工作:
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{luacode}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{luacode}
function gcd(a,b)
if b ~= 0 then
return gcd(b, a % b)
else
return math.abs(a)
end
end
\end{luacode}
\newcommand\findgcd[1]{\directlua{tex.sprint(gcd(#1))}}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\ifnum\findgcd{\m,\n}=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi
}
\end{tikzpicture}
\end{document}
所有上述方法都将输出以下内容:
答案2
这里有两个问题。(都需要理解 TeX 才能理解解决方法。)
\py
没有扩展其论点。
(类型 3 的我对嵌套宏的回答。 也可以看看如何在 pythontex 中将章节编号传递给 python? - TeX - LaTeX Stack Exchange——没有学习 TeX 编程就没有完全自动化的解决方案然而。
这里的一个解决方案是使用\expanded
(参见下面代码中插入的代码)。替代方案包括 edef、ExpandArgs、exp_args:Nx 等。(另请参阅上面链接的答案中链接的问题)
警告:\expanded 可能不是每次都能达到你想要的效果. 确保您理解代码的作用,以便修改它。
\py
不可扩展。
(类型 2 的我的答案如下。
该问题已记录在 pythontex 手册中。
(我在这里附上了一张截图。如果您想阅读文本,请阅读手册。)
一种解决方法是遵循这一点,并定义一个打印出整个外部内容的 Python 函数。
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{pythontex}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{pycode}
def ggt(a,b):
r=a%b
i=0
erg=1
while r:
a=b
b=r
r=a%b
return b
def print_my_command(m, n):
print(
r'\ifnum' + str(ggt(m, n)) + r'''=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi'''
)
\end{pycode}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\expanded{\pyc{print_my_command(\m,\n)}}
}
\end{tikzpicture}
\end{document}
虽然如果你这样做,你最好在 Python 中检查一下。print_my_command
用
def print_my_command(m, n):
if ggt(m, n)==1:
print(r""" \node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$}; """)
else:
print(r""" \node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$}; """)
您还可以在 Python 端将 替换\m
为 的值。m
另一种解决方法,这个需要更多的 TeX 知识,是使用临时变量,如我上面链接的答案中所述。
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{pythontex}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{pycode}
def ggt(a,b):
r=a%b
i=0
erg=1
while r:
a=b
b=r
r=a%b
return b
def my_set_ggt(m, n):
print(r"\def\mytmpggt{" + str(ggt(m, n)) + "}")
\end{pycode}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\def\mytmpggt{0}
\expanded{\pyc{my_set_ggt(\m,\n)}}
\ifnum\mytmpggt=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi
}
\end{tikzpicture}
\end{document}
边注,括号内的内容\ifnum
与你想象的并不一样。如果你想学习,请阅读 TeXbook(或 TeX by Topic,TeX in a nutshell)。
答案3
既然您要求替代方法:
您可以替换pythontex
为pyluatex
.
你必须使用 LuaLaTeX 进行编译:lualatex -shell-escape <yourfile.tex>
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{pyluatex} % <--- changed
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{python} % <--- changed
def ggt(a,b):
r=a%b
i=0
erg=1
while r:
a=b
b=r
r=a%b
return b
\end{python} % <--- changed
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\ifnum\py{ggt(\m,\n)}=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi
}
\end{tikzpicture}
\end{document}
然后你甚至可以使用以下\pyif
命令:
\pyif{ggt(\m,\n) == 1}{
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};
}{
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}