我尝试查看mult
、、div
等如何add
工作,但我无法理解一个具体示例中发生了什么。假设我想在 x = y = 2 处放置一个点,但 x 和 y 坐标来自一些复杂的几何计算。以下代码片段可实现此目的:
\begin{pspicture}[showgrid=true](0,0)(5,5)
\pnode(!0 2 add 2){C}
\psdot(C)
\end{pspicture}
然而,我对发生的事情感到非常困惑:一个点由两部分信息组成,x 坐标和 y 坐标。我所期望的最直观的事情是
\pnode(!0 2 add, !0 2 add){C}
但这会产生错误。所以我花了一些时间才弄清楚
\pnode(!0 2 add 0 2 add){C}
满足了我的要求。我的问题是:发生了什么?为什么人们要这样编码?
这不是直观的,而是*反*直观的 :-) 这其中是否存在我现在看不到的意义?
答案1
感叹号表示原始的 PostScript 代码。由于 PostScript 是一种堆叠语言,因此当您执行
\pnode(!0 2 add 0 2 add){C}
发生以下情况。
0 2
被推入堆栈。add
抓住顶部的两个对象,将它们相加并将结果推送到堆栈上。0 2
被推入堆栈,因此现在堆栈顶部的三个对象是2 0 2
。- 添加操作与之前相同,因此最终堆栈包含
2 2
在顶部。
当然,你也可以使用
\pnode(!2 2){C}
有一些不错的 PostScript 手册可供使用这里。
答案2
这是 PostScript 代码的一个示例。其中使用了所谓的逆波兰表示法。例如 (2+3)*4 写为
2 3 add 4 mul
,其中add
表示加法和mul
乘法。
它并不违反直觉。例如,在纯 TeX 中,分数通过$a\over b$
(参数之间的运算符) 获得,在 LaTeX 中,分数通过\frac{a}{b}
(参数之前的运算符) 获得。在逆波兰表示法中,分数将是{a}{b}\frac
。
答案3
来自pstricks
文档(部分54 特殊坐标,第 145 页):
(!ps)
原始 PostScript 代码。ps
应扩展为坐标对。使用单位xunit
和yunit
。例如,如果我们想使用与和一起缩放的极坐标 (2, 45) 和 (1.5, 70)xunit
,yunit
我们可以这样写:\SpecialCoor \psset{dotscale=2,xunit=2,yunit=1.5}% \psdot(2;45) \psdot[linecolor=cyan](! 2 45 cos mul 2 45 sin mul) \psset{dotstyle=triangle*}% \psdot(1.5;70) \psdot[linecolor=cyan](! 1.5 70 cos mul 1.5 70 sin mul)
很多事情都可以用 PostScript 编程来完成,有时甚至比在 TeX 级别上更容易。还请注意,除了计算坐标外,还可以执行一些 PostScript 代码。
请注意,坐标之间没有逗号!
因此,在调用 之后\SpecialCoor
,符号(! <stuff>)
表示设置坐标的 PostScript 接口。并且,PostScript 使用逆波兰表示法 (RPN)将内容推送/弹出到堆栈的方法。通俗地说,这意味着(使用中缀表示法)在 RPN 中3 − 4 + 5
转换为3 4 − 5 +
- 首先指定操作数,然后指定作用于这些操作数的运算符。具体到您的示例,传递给 PostScript 编译器的坐标对需要两个顶部条目类似于您的 (X,Y) 对。如果您推送一个 X 值,后跟一个逗号,
,后跟一个 Y 值,PostScript 编译器可能会将其,
视为 X 值,这没有意义。
pstricks
有关 PostScript 语言(在后台广泛使用)的详细讨论,请参阅PostScript 语言参考手册。特别是,你应该阅读关于运算符的章节(第 8 章:运算符,第 505 页)。
按顺序,\pnode(!0 2 add 0 2 add){C}
具有以下 PostScript 序列:
0
被推入堆栈(堆栈0
:)2
被推入堆栈(堆栈0 2
:)add
取出堆栈上的前两个条目并将其替换为总和 (stack:2
)0
被推入堆栈(堆栈2 0
:)2
被推入堆栈(堆栈2 0 2
:)add
取出堆栈上的前两个条目并将其替换为总和 (stack:2 2
)
正如文档中提到的pstricks
,在 PostScript 方面可以做很多事情(例如,读取任何.pro
与 关联的文件pstricks
)。如果您希望自行更新某些pstricks
功能。
答案4
后缀表达式(又名 RPN)中的点必须留下 2 个值(在堆栈上),分别表示该点的横坐标和纵坐标。
后缀表达式中的点有一个起始分隔符
!
。,
横坐标与纵坐标之间没有。
例子
(!1 2)
是相同的(1,2)
。(!2 dup)
(2 2)
与dup
表示复制前一个值相同。(!1 2 sub 3 4 add)
是相同的(-1,7)
。(!1 2 exch)
(2,1)
与exch
表示交换前两个值相同。- 等等(通过发表一些评论来询问)。