TeX 使用缩放点作为其最小单位。至少在电子书:
TeX 在内部将所有维度表示为称为 sp 的微小单位的整数倍。
65536 sp = 2^{16} sp = 1 pt。
后来,
TeX 实际上使用 2^{-16} 的整数倍进行计算...
但,编译它你会看到,0.00000762939453125 开始与零区分开来,这意味着它是 TeX 的最小单位。(0.00000762939453125 正好是 2^{-17})
\line{\hskip 0pt plus 16383.99999fil and now?\hskip 0pt plus 0.000007629394531249fill}
\line{\hskip 0pt plus 16383.99999fil and now?\hskip 0pt plus 0.000007629394531250fill}
\bye
那么,真实的最小单位:2^{-16} 还是 2^{-17}?
答案1
当你说
\dimen0=0.00000762939453125pt
指令\showthe\dimen0
将回答
> 0.00002pt.
因为这就是 1sp 以点表示的样子。
会发生什么?TeX 在程序内部进行二进制算术运算。输入的数字被识别为大于零(应该查看程序代码),因此维度被设置为最小正数。
同样地,之后
\skip0=0pt plus 0.000007629394531250fill \showthe\skip0
你得到
> 0.0pt plus 0.00002fill.
所以绝不是小于 1sp 的正维度。您使用的输入可以出现小于 1sp 的情况,但 TeX 使用的值是 1sp。
的模块 102 中描述了从十进制数到缩放整数的转换tex.web
;整数部分仅乘以 65536,因此它只对 0 形式的数字感兴趣。d0d1 …dk–1
最终缩放的整数存储在A初始化为 0。然后我们从最右边开始,每一步A被分配结果
(A+d我* 2 17 )div10
最后,A被分配值(A+ 1)div2(带截断)
如果我们执行这个算法,我们会得到以下数字作为A(括号内为所检查的数字)
(5) 65536
(2) 32768
(1) 16384
(3) 40960
(5) 69632
(4) 59392
(9) 123904
(3) 51712
(9) 123136
(2) 38528
(6) 82496
(7) 100000
(0) 10000
(0) 1000
(0) 100
(0) 10
(0) 1
final step (1+1) div 2 = 1
这div操作通过截断进行。
我留下一个练习来证明 0.0000152587890625 = 2 –16也产生 1,而 0.000007629394531249 则产生 0。
可以看到,该算法采用217来保证小数部分的16位精度。
答案2
当您输入某个尺寸作为某个(正)小数点数时,它将被四舍五入为最接近的整数倍1/65536 pt = 1sp
,其中包括N.5
到(N+1).5
不包括的数字将四舍五入为N+1
。
以下实验可以说明这一点。它们需要 e-TeX 扩展(使用pdftex
或进行编译etex
),但我检查了 Knuth 中是否遵循了这些结论tex
。
egreg
我还通过数学方法验证了答案中描述的特定算法确实能产生我在这里所说的结果。见下文。
% compile with etex or pdftex
\input xintexpr.sty
\tt
\def\Test #1{% #1 = integer
\def\a {#1/65536}%
\def\b {(#1+1)/65536}%
\def\delta {1/65536}%
This is #1/65536 in decimal: \xinttheiexpr [30]\a \relax.\endgraf
This is (#1+1)/65536 in decimal: \xinttheiexpr [30]\b \relax.\endgraf
\def\Iterate {%
\edef\c {\xinttheiexpr [30](\a+\b)/2\relax }%
\ifnum\number\dimexpr \c pt\relax >#1
\let\b\c
\else
\let\a\c
\fi
\edef\delta {\xinttheexpr \delta/2\relax }%
}%
\loop
\Iterate
\xintifboolexpr {\delta < 10^(-25)}{\iffalse}{\iftrue}%
\repeat
\edef\A {\xinttheiexpr [30]\a*65536\relax}%
\edef\B {\xinttheiexpr [30]\b*65536\relax}%
$\a \approx {\A\over 65536}$\endgraf
$\a$ pt is represented internally as
$\number\dimexpr \a pt\relax$ (sp).\endgraf
$\b \approx {\B \over 65536}$\endgraf
$\b$ pt is represented internally as
$\number\dimexpr \b pt\relax$ (sp).\endgraf
\vskip.5cm
}
\Test {0}
\Test {1}
\Test {2}
\Test {3}
\Test {17}
\Test {123456789}
\nopagenumbers
\bye
(更新纠正了索引中的拼写错误)
\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{geometry}
\usepackage{newtxtext,newtxmath}
\let\leq\leqslant
\let\geq\geqslant
\begin{document}\pagestyle{empty}
Let us start from a decimal number $x$ in $[0,1)$ with $k$ digits after
decimal mark.
\[ x = 0.d_k\cdots d_1\]
Enumerating the digits this way facilitates my description next. We set
$a_0=0$ and define repetitively up to $j=k$ the following non-negative integers:
\[ a_{j+1} = \lfloor \frac{a_j + 2^{17}\cdot d_{j+1}}{10}\rfloor \]
Once we reach $a_k$ we do a final definition:
\[ a = \lfloor \frac{a_k+1}2 \rfloor\]
By definition
\[ a_1 \leq \frac{d_1\cdot 2^{17}}{10} < a_1 + 1\]
\[ 10a_1 \leq d_1 \cdot 2^{17} < 10a_1 + 10\]
Because everything in sight is integer valued, we can improve this to:
\[ 10a_1 \leq d_1 \cdot 2^{17} \leq 10a_1 + 9\]
Similarly
\[a_2 \leq \frac{a_1 + d_2\cdot 2^{17}}{10} < a_2 + 1\]
\[ 10a_2 \leq a_1 + d_2 \cdot 2^{17} < 10a_2 + 10\]
Again everything in sight is integer valued:
\[ 10 a_2 \leq a_1 + d_2 \cdot 2^{17} \leq 10a_2 +9 = 10a_2 + 10 - 1\]
We transform this into
\[ 10^2 a_2 \leq 10^1 a_1 + 10^1 d_2\cdot 2^{17}\leq 10^2 a_2 + 100 - 10\]
Then, similarly
\[10^3 a_3 \leq 10^2 a_2 + 10^2 d_3\cdot 2^{17}\leq 10^3 a_3 + 10^3 - 10^2\]
\[10^4 a_4 \leq 10^3 a_3 + 10^3 d_4\cdot 2^{17}\leq 10^4 a_4 + 10^4 - 10^3\]
up to
\[10^k a_k \leq 10^{k-1}a_{k-1} + 10^{k-1}d_{k}\cdot 2^{17}\leq 10^k a_k +
10^k - 10^{k-1}\]
If we add up everything and simplify the common terms we end up with
\[ 10^k a_k\leq (10^{k-1}d_{k}+\cdots + d_1)\cdot 2^{17}\leq 10^k a_k + 10^k
-1\]
Thus
\[ \frac{a_k}2 \leq 2^{16}\cdot x \leq \frac{a_k + 1 - 10^{-k}}2 <
\frac{a_k+1}2\]
If $a_k = 2j$ is even, the rule of \textsc{D.~Knuth} is now to set $a = j$ and
this $j$ satifies
\[ j \leq 2^{16}\cdot x < j + 0.5\]
If $a_k = 2j+1$ is odd, the rule of \textsc{D.~Knuth} is to set $a = j+1$ and
we have
\[ j + 0.5 \leq 2^{16}\cdot x < j +1\]
Hence in all cases we have the formula:
\[ a = \lfloor 2^{16}\cdot x+0.5\rfloor\]
in other words $a$ is the \textbf{rounded} value of $2^{16}\cdot x$.
As originally claimed by your humble servant.
Sincerely,\par
Mercredi 04 mars 2015 à 15:27:34\par
typo corrected Mercredi 04 mars 2015 à 16:01:51
\vskip.2cm
\hrule
\end{document}
我还想补充一些额外的论点来解释为什么 TeX 的扫描会丢弃小数点后除前十七位数字之外的所有数字:
(更正了拼写错误,事实并非§452
如此§402
)
为了消除潜在的混淆,请记住,上述内容仅适用于形状为的十进制数0.abcedf...
。点之前的数字是单独处理的,只有点之后的数字才需要保留最多 17 位。