值\MM
等于1mm
并且内部存储为2.84526pt
。值\MMQUARTER
等于0.25mm
并且应该存储为0.711315pt
( 2.84526/4 = 0.711315
) 但是存储为0.7113pt
。我需要找到一个解决方案来防止 被截断0.000015
。
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgfmathsetlengthmacro{\MM}{1mm}
\pgfmathsetlengthmacro{\MMQUARTER}{0.25mm}
\path node[align=left]
{%
\pgfmathparse
{% 'MM' IS 2.84526
\MM
} \pgfmathresult
% NEXT LINE CAN BE IGNORED
\hspace{0.33cm} = 1mm
\\ % NEW LINE
\pgfmathparse
{% 'MMQUARTER' MUST BE 0.711315 BUT IS 0.7113
\MMQUARTER
} \pgfmathresult
% NEXT 3 LINES CAN BE IGNORED
\hspace{0.5cm} $\approx$ 0.25mm;
\\ % NEW LINE
\hspace{1.5cm} must be 0.7113\textcolor{red}{15} (exactly 0.25mm)
};
\end{tikzpicture}
\end{document}
答案1
第一句话有点误导
值 \MM 等于 1mm,内部存储为 2.84526pt
TeX (几乎) 从不使用浮点运算,并且从不在 TeX 内部可检测到机器运算差异的地方使用它。
几乎所有的算术都是精确的整数算术,为了显示目的而进行十进制转换。
TeX 使用转换 25.4mm=1in=72.27pt, 65536sp=1pt
所以 1mm 是 186467sp,这个整数就是长度
除以 4 并向下舍入得到 46616sp,显示为 0.7113pt。
您可以通过在命令行上运行 tex 以交互方式查看这些值:
$ tex
This is TeX, Version 3.14159265 (TeX Live 2017) (preloaded format=tex)
**\dimen0=1mm
*\count0=\dimen0
*\showthe\count0
> 186467.
<*> \showthe\count0
?
*\divide\count0 by 4
*\showthe\count0
> 46616.
<*> \showthe\count0
?
*\dimen0=\count0 sp
*\showthe\dimen0
> 0.7113pt.
<*> \showthe\dimen0
? x
No pages of output.
Transcript written on texput.log.
答案2
让我首先评论一下你代码中的注释
\pgfmathsetlengthmacro{\MM}{1mm}
\pgfmathsetlengthmacro{\MMQUARTER}{0.25mm}
{% 'MM' IS 2.84526
\MM
{% 'MMQUARTER' MUST BE 0.711315 BUT IS 0.7113
\MMQUARTER
我认为\pgfmathsetlengthmacro
在某个时候,这在内部可以归结为标准 TeX。像这样的尺寸规范0.25mm
就是这样解析的。我将用术语来描述它,不是逐一对应 TeX 处理,而是产生完全相同的结果。
首先
0.25
是圆形为整数倍N/65536
。此处为精确匹配N=16384
。然后应用转换因子,对于单位来说,转换因子
mm
是(根据tex.web §458
)7227/2540
。这意味着 TeX 评估截断为整数的精确分数16384*7227/2540
。现在:
$ rlwrap etex This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/MacPorts 2017_1) (preloaded format=etex) restricted \write18 enabled. **xintexpr.sty entering extended mode (/usr/local/texlive/2017/texmf-dist/tex/generic/xint/xintexpr.sty (/usr/local/texlive/2017/texmf-dist/tex/generic/xint/xintfrac.sty (/usr/local/texlive/2017/texmf-dist/tex/generic/xint/xint.sty (/usr/local/texlive/2017/texmf-dist/tex/generic/xint/xintcore.sty (/usr/local/texlive/2017/texmf-dist/tex/generic/xint/xintkernel.sty)))) (/usr/local/texlive/2017/texmf-dist/tex/generic/xint/xinttools.sty)) *\message{\xinttheiexpr [40] 16384*7227/2540\relax} 46616.9952755905511811023622047244094488188976 *\bye No pages of output. Transcript written on xintexpr.log.
所以在这种情况下 TeX 将会获得
46616
,我们看到它在这里犯了一个相对较大的错误。结论是,
0.25mm
在内部存储为,46616sp
其中1sp
是65536th
(TeX) 的一部分pt
。
有关详细信息,请参阅为何pdf文件无法复制?
46616sp
那么,当使用 显示内部存储为 的尺寸时会发生什么\the
?该算法是§103
并且tex.web
有点微妙。我们想要生成一个pt
单位值,它将精确地重现46616sp
if圆形的整数倍1/65536
。当然,我们首先处理整数部分,这里整数部分消失了。因此,我们假设我们有一些初始值n
。Knuth0 <= n < 65536
实际上(间接地)考虑了 的十进制展开(n + 0.5)/65536
。假设我们查看K
这个十进制展开的前几位数字,因此,对于K = 1, 2, 3, 4
并且最多5
,我们有
(n+0.5)/65536 = D_K/10^K + N_K/(10^K \times 65536)
对于N_K
那些K
被认为是整数,正数,且严格小于65536
(二乘法的考虑证明了我的一些断言)。N_K
只需重复乘以10
模即可获得65536
。上面的等式给出
65536 D_K/10^K = n + 0.5 - N_K/10^K
如果对于任意一个K
我们观察到0< N_K <= 10^K
(已知正性),则四舍五入的将按预期65536 D_K/10^K
返回。这可能发生在、... 或。想象一下它没有发生。那么它必然会在但这种情况是特别处理的。如果我们达到它是因为我们有。然后让我们。它是,所以我们写其中是数字。简化后我们得到n
K = 1
4
K = 5
K = 5
N_4 > 10000
M_5 = 10 N_4 - 50000 + 32768
> 65536
M_5 = q 65536 + r
q
n = 65536 (10 D_4 + q)/100000 + (r - 32768)/100000
并且D_5 = 10 D_4 + q
具有第五位数字,我们再次得到一个小数,将其四舍五入D_5/100000
为的整数倍得到。(我将不得不再次阅读但这是我对它的印象)。1/65536
n/65536
§103
tex.web
我们可以按照 的步骤进行操作n = 46616
。首先我们计算10(46616.5) = 466165 = 7x65536+7413
给出N_1 = 7413
。它不是<= 10
,因此算法继续。第一个数字是7
。
Python 3.5.4 |Continuum Analytics, Inc.| (default, Aug 14 2017, 12:43:10)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> divmod(74130,65536)
(1, 8594)
>>> divmod(85940,65536)
(1, 20404)
>>> divmod(204040,65536)
(3, 7432)
因此数字为7
,1
,1
,3
,这里我们得到N_4 = 7432
小于10000
。算法在这里停止,因此 TeX 生成0.7113pt
。
从上面的描述中,你可以看到它永远不会产生小数点后 6 位数字,例如0.711315
。要获得这一点,你必须使用数学引擎(可能在宏中实现;因为 1999 年的 e-TeX\numexpr
更容易扩展地做到这一点,至少在理论上是这样)能够处理这样的十进制数。
您可以使用\xinttheiexpr [D]
宏进行此类计算,其中D
是所要求的最终结果小数点后的数字位数,但计算是精确完成的。
回到四分之一毫米(使用 Plain TeX,在 LaTeX 中也可以使用\usepackage{xintexpr}
):
\input xintexpr.sty
\xintdefvar mm:= 7227/2540;
\edef\MYQUARTERMM{\xinttheexpr trunc(0.25mm, 40)\relax}
\show\MYQUARTERMM
\bye
在日志中生成
> \MYQUARTERMM=macro:
->0.7113188976377952755905511811023622047244.
l.7 \show\MYQUARTERMM
顺便说一句,这表明0.711315
原问题中出现的“as”的含义并不那么清楚。
从上可知,先验更接近的 6 位近似值是0.711319pt
。经过检查,我们可以看出和都0.711319pt
被0.711315pt
TeX 转换为内部表示46617sp
(\number\dimexpr 0.711319pt\relax
,\number\dimexpr 0.711315pt\relax
)。
并\the\dimexpr 0.711319pt\relax
输出0.71132pt
。因此,这0.71132pt
是最准确的 5 位数字表示(经过测试,它是唯一46617sp
内部给出的)实际精确0.25mm
尺寸。但是如上所述,当 TeX 遇到 时,0.25mm
它将获得46616sp
。使用更大的cm
单位会导致0.025cm
更大的精度损失(46605sp
)。