尝试定义变量时,单位非法,且缺少数字

尝试定义变量时,单位非法,且缺少数字

当尝试制作一系列阶跃函数图形时,我写了以下代码片段:

\begin{tikzpicture}
\pgfmathsetmacro{\n}{2^3};
\pgfmathsetmacro{\step}{1/\n};
\foreach \i in {0,\step,...,(\n-1)*\step}
            {\draw[-,thick,blue] (\i,{\i*2})--({\i+\step},{\i*2});}
\end{tikzpicture}

我的想法是,我想定义变量\n\step这样我所要做的就是调整\n设置的值,然后它将在很多大小相同的部分中绘制一个阶跃函数,等等等等。我将使用它在同一个文档中制作许多不同的图片。

但是,似乎以这种方式定义变量是不合法的 - 至少,我是这样认为的,因为当我不使用变量编写这个程序时它似乎工作正常。

有没有办法在tikzpicture环境中“全局”定义变量?


我突然想到......我可以执行以下操作吗?

\begin{tikzpicture}
\foreach \n in {2^3} {
\foreach \step in {1/n} {
\foreach \i in {0,\step,...,(\n-1)*\step}
            {\draw[-,thick,blue] (\i,{\i*2})--({\i+\step},{\i*2});}
}}
\end{tikzpicture}

即使它有效,它也确实看起来像一个脆弱的黑客...而且我猜一定有某种原因导致我从未见过有人建议这样做...尽管我实际上无法说出它不好的原因。

有什么原因导致它不起作用或者不好吗?


更新:测试了一下,虽然没有完全损坏,但并没有完全起作用,但仍在试图理解它为什么会这样做。

答案1

循环\foreach不会自行评估其列表的任何条目。并且在语法之后,...它需要“看到”一个有效的数字。

在这种情况下,您可以parse = true强制 PGFFor 评估其列表中的最后一个条目。

在第二种情况下,我使用use float来自ext.misc我的tikz-ext包的库的密钥。请注意,它是在声明变量后使用的,并且没有任何in <list>部分!此密钥将为您评估所有条目。

在第三和第四种情况下,我使用整数步长,并且只缩放绘图或坐标坐标系。这样我们就可以避免可能出现的浮点数误差。(不过,在我下面使用的例子中,它们并不存在。)

在第五种情况下,我使用了一个绘图来帮我们完成所有计算。当然,这只是本例中的有效解决方案。

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{ext.misc}
\makeatletter
\tikzset{scale xyz/.code=\pgfmathparse{#1}%
  \pgf@xx\pgfmathresult\pgf@xx \pgf@xy\pgfmathresult\pgf@xy
  \pgf@yx\pgfmathresult\pgf@yx \pgf@yy\pgfmathresult\pgf@yy
  \pgf@zx\pgfmathresult\pgf@zx \pgf@zy\pgfmathresult\pgf@zy}
\makeatother
\newcommand*\myRow[1]{
  \node[right] at (0,1) {$n = \pgfmathprint{int(#1)}$};
\pgfmatrixnextcell
  % Case 1: everything the same but parse the last entry
  \pgfmathsetmacro{\n}{#1}
  \pgfmathsetmacro{\step}{1/\n}
  \foreach[parse=true] \i in {0, \step, ..., (\n-1)*\step}
    \draw (\i,\i*2) -- +(right:\step);
\pgfmatrixnextcell
  % Case 2: use float = <start> to <end> step <step>
  \foreach \i[use float = 0 to (#1-1)/#1 step 1/#1]
    \draw (\i,\i*2) -- +(right:1/#1);
\pgfmatrixnextcell
  % Case 3: use integer steps (and parsing the last entry)
  %         and divide by #1 when drawing
  \foreach[parse=true] \i in {0,...,#1-1}
    \draw (\i/#1,2*\i/#1) -- +(right:1/#1);
\pgfmatrixnextcell
  % Case 4: scale xyz coordinate system by 1/#1
  %         and use integer steps
  \tikzset{scale xyz = 1/#1}% i.e. scale = 1/8
  \foreach[parse=true] \i in {0,...,#1-1}
    \draw (\i,2*\i) -- +(right:1);
\pgfmatrixnextcell
  % Case 5: Maybe a plot?
  \draw[scale xyz=1/#1] plot[jump mark left, domain=0:#1, samples=#1+1] (\x,2*\x);
\pgfmatrixendrow}
\begin{document}
\tikz[
  row sep=5mm, column sep=5mm, thick, blue,
  every cell/.style 2 args={
    style/.expand twice={\ifnum#2>1 \ifnum#1>1
      execute at begin cell={\draw[help lines] (0,0) grid (1,2);}\fi\fi}}]
\matrix[row 5/.style=thin, row 1/.style={shift=(right:.5)}]{
&\node{Case 1}; &\node{Case 2}; &\node{Case 3}; &\node{Case 4}; &\node{Case 5};\\
  \myRow{2^3} \myRow{3^3} \myRow{5} \myRow{35} \myRow{73}};
\end{document}

输出

在此处输入图片描述

答案2

我会使用更好的浮点系统。

\documentclass{article}
\usepackage{tikz}

\ExplSyntaxOn
\NewDocumentCommand{\fpstep}{mmmm}
 {
  \fp_step_inline:nnnn { #1 } { #2 } { #3 } { #4 }
 }
\NewDocumentCommand{\definefpvar}{mm}
 {
  \fp_zero_new:c { l_addem_fpvar_#1_fp }
  \fp_set:cn { l_addem_fpvar_#1_fp } { #2 }
 }
\NewExpandableDocumentCommand{\fpvar}{m}
 {
  \fp_use:c { l_addem_fpvar_#1_fp }
 }
\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
  \definefpvar{n}{2^3}
  \definefpvar{step}{1/(\fpvar{n})}
  \fpstep{0}{\fpvar{step}}{(\fpvar{n}-1)*\fpvar{step}}
   {\draw[-,thick,blue] (#1,{#1*2})--({#1+\fpvar{step}},{#1*2});}
\end{tikzpicture}

\end{document}

而不是\foreach,因为它对浮点值的表现实际上并不十分准确,而是\fp_step_inline:nnnn使用 函数。第四个参数#1代表循环中的当前值。第一个参数是起点,第二个参数是步骤,第三个参数是终点。

在此处输入图片描述

相关内容