答案1
告诉 Metapost 使用更好的精度(参见Metafun 手册)。
\startMPpage[instance=decimalfun]
numeric u;
path yy;
u:= 3cm;
for i=0 step 2/10 until 2:
draw (left--right) shifted (0,i*u); label.lft(textext(decimal(i)), (-2,i*u));
endfor;
yy = (down-- 2 up) scaled u;
draw yy;
\stopMPpage
答案2
您的代码没有任何问题,本身。问题是(默认情况下)MetaPost 使用二进制数字系统(实际上是缩放点算法,非常像 TeX)。MetaPost 用户手册附录 A 对此进行了如下描述。
数字系统
scaled
参考第 6.1 节描述的 32 位定点算法。
所有二进制数字系统都存在的一个常见问题是准确存储某些十进制值。引用同一节的内容:
关键在于,使用 2 进制 [...] 数字无法准确表示某些十进制数,其中包括像 0.1 这样的奇怪数字。在 2 进制 [...] 数字格式中,此值具有无限 [原文如此] 重复表示,如果不引入舍入误差,则无法将其存储在有限精度的尾数中。
幸运的是,MetaPost 的一个有趣之处是,我们可以在几个不同的数字系统之间进行选择。它们是:
- 缩放(32 位二进制,缩放点;默认值),
- 双精度(64 位二进制,浮点),
- 二进制(可变精度二进制,浮点),
- 十进制(可变精度十进制,浮点数)。
使用十进制当然会降低性能,但作为交换,你可以精确地表示诸如 0.2 之类的值。实际上,在 TeX 执行的其他所有操作中,你可能不会注意到其中的差异。
那么,如何告诉 ConTeXt 使用哪个数字系统呢?您可以告诉 ConTeXt 使用不同的 MetaPost“实例”,该实例已配置为使用特定的数字系统。有各种预定义的实例;为了我们的目的,我们提到了其中四个:
metafun
(默认实例)使用缩放,doublefun
使用双重,binaryfun
使用二进制,decimalfun
使用十进制。
环境MPcode
采用可选参数来告诉它要使用哪个实例。因此,改变
\startMPcode
...
\stopMPcode
到
\startMPcode{decimalfun}
...
\stopMPcode
将与实例一起运行代码decimalfun
,从而“修复”您的代码。
\setupMPinstance[method=<method>]
另一种可能性是,在代码前说明,<method>
其中是值scaled
、double
、binary
和之一decimal
。然后所有实例都将使用该数字系统。具体来说,将代码更改为
\setupMPinstance[method=decimal]
\startMPcode
...
\stopMPcode
也将解决这个问题。
答案3
Metapost 在浮点数加法方面不太擅长;不过,它对 10 的除法比较擅长。
\documentclass{article}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
beginfig(1);
numeric u;
path yy;
u:= 3cm;
for i=0 step 2 until 20:
draw (left--right) shifted (0,i*u/10); label.lft(textext(decimal(i/10)), (-2,i*u/10));
endfor;
yy = (down-- 2 up) scaled u;
draw yy;
endfig;
\end{mplibcode}
\mplibnumbersystem{decimal}
\begin{mplibcode}
beginfig(2);
numeric u;
path yy;
u:= 3cm;
for i=0 step 2/10 until 2:
draw (left--right) shifted (0,i*u); label.lft(textext(decimal(i)), (-2,i*u));
endfor;
yy = (down-- 2 up) scaled u;
draw yy;
endfig;
\end{mplibcode}
\end{document}
decimal
(抱歉,我没有 ConTeXt)。我不知道如何在 ConTeXt 中传递数字系统,但无论如何这只是一个例子。