我遇到了一个有趣的问题。很久以前我创建了一个 pdf 文件。可以下载这里。现在,为了回忆一下它是如何生成的,我决定重复该过程并比较 pdf 文件。我快要成功了,但我无法让新旧 pdf 文件看起来一样。我记得我按照通常的方式做了所有事情,我只是改变了边距。
为何pdf文件无法复制?
这是生成新的pdf文件的过程:
1)从以下位置获取最新的 cweb 源ftp://ftp.cs.stanford.edu/pub/cweb/cweb-3.64ah.tgz
2)cwebmac.tex
改为{NOS} fith
手动{NOS} fitb
或使用此命令
perl -i -pe 's/{NOS} fith/{NOS} fitb/' cwebmac.tex
3)将以下内容添加到cwebmac.tex
\let\Blue=\Black
\hoffset=1.52400970458984374999999999999cm
\pageshift=2in
\advance\pageshift by-\hoffset
\advance\hoffset by-1in
\advance\pageshift by-1in
4)构建cweave
touch *.c
make
5)cweave
继续cweave.w
./cweave cweave.w
6)生成pdf文件:
SOURCE_DATE_EPOCH=1460880679 pdftex cweave.tex
7) 现在我们将旧 pdf 与新 pdf 进行比较。为此,我们必须解压缩 pdf 文件中的对象。
qpdf --qdf --object-streams=disable cweave.pdf cweave-long.pdf
qpdf --qdf --object-streams=disable cweave-old.pdf cweave-old-long.pdf
diff -u cweave-old-long.pdf cweave-long.pdf
我们在 diff 中看到,新 pdf 中的许多值比旧 pdf 中的值小 0.001。但我无法让这个 0.001 消失。如果我设置\hoffset
为1.52400970458984375
,新 pdf 中的值将0.001
大于旧 pdf 中的值。如果我设置\hoffset
为52400970458984374999999999999
,新 pdf 中的值将比0.001
旧 pdf 中的值小。我对此完全感到困惑。另外,我记得要设置\hoffset
为一些简单的东西,比如1.5cm
,而不是我通过反复比较 diff 凭经验构建的这个值。
此外,一些连字符也发生了变化。例如,新旧 pdf 文件中以下内容有所不同:
-/F13 9.9626 Tf 125.8 495.045 Td [(i)]TJ/F3 7.9701 Tf 13.837 0 Td [(Used)-354(in)-354(secti)-1(o)1(n)]TJ
+/F13 9.9626 Tf 125.799 495.045 Td [(i)]TJ/F3 7.9701 Tf 13.837 0 Td [(Used)-354(in)-354(se)-1(ction)]TJ
即如何
[(Used)-354(in)-354(secti)-1(o)1(n)]TJ
不同于
[(Used)-354(in)-354(se)-1(ction)]TJ
? 但更重要的是,为什么有什么不同吗?这个 pdf 代码到底是什么意思?
为何pdftex
无法重现pdf文件?
这是下载差异文件的链接:https://www.dropbox.com/s/lvbijcn2689cuye/cweave.diff?dl=1
答案1
最后补充:什么时候<foo> cm = <bar> in
对 TeX 成立?
传递数学细节和除非我的数学监督快的调查将 四舍五入为 的整数倍数会得出 ,并且是 的倍数,这是必要<foo>
且充分的。f/65536
1/65536
f
127
只有这样,才会有某些<bar> in
东西给出完全相同的 TeX 维度。将 舍入为的<bar>
整数倍数将是的倍数。反之亦然。g/65536
1/65536
g
50
例如:我们寻找附近的这样一个维度。我们需要附近0.6in
的倍数,因此或。前者是通过(和附近的小数)获得的,后者是通过(和附近的小数)获得的。50
0.6*65536=39321.6
39300
39350
0.59967in
0.60043in
事实上,对于 TeX,我们有
0.59967in = 1.52316cm = 2840211sp
0.60043in = 1.52510cm = 2843824sp
\number\dimexpr0.59967in\relax =\number\dimexpr1.52316cm \relax
\number\dimexpr0.60043in\relax =\number\dimexpr1.52510cm \relax
\bye
但是,正如 OP 的主要原因一样,0.6in
没有使用cm
单位的精确等价物。就单位而言,允许表示为和 的sp
可能值是某个整数 的那些。上面,分别是和。N sp
<foo> in
<bar> cm
N = int(3613.5*k)
k
k
786
787
更新:解释 TeX 如何扫描尺寸
下文和评论中已澄清,造成差异的原因在于您以前使用in
为维度单位,而在重建尝试中使用。此外,使最初以 表示的两个维度之间的差异与直接以 表示结果cm
并不完全相同,因为不是TeX 使用的最小单位 的整数。in
in
1in
sp
在https://tex.stackexchange.com/a/231281/4686我解释了 TeX 如何处理像 这样的维度abc.xyz... pt
。这来自tex.pdf
(texdoc tex.pdf) 的 §452。事实证明该部分也适用于abc.xyz... in
,因此我回想起了结果:
将分数 abc.xyz... 四舍五入(远离零的四舍五入)为 1/65536 的整数倍
在这个过程中,算法可能会丢弃(不影响理论结果)小数点后除前17位数字以外的所有数字。
假设我们得到了以对的形式解开的“解包”结果(n, f)
,它在此阶段表示分数(65536n+f)/65536
。
现在 TeX 考虑了维度单位。这在 的 §458 中进行了解释tex.pdf
。简单的情况是pt
(之前在 §453 中处理过),TeX 只是将其放入65536*n+f
寄存器中。对于 的情况in
,我们在道义上需要这样做(65536*n+f)*7227/100
。当然,这里的问题是不要使用整数算术产生溢出。执行此操作的例程在 §107。让我们写x=65536*n+f
。操作(这里简化了,没有符号,没有溢出截距)是
t<- (x mod 32768)*7227
u <- (x div 32768) * 7227 + (t div 32768)
v <- (u 模 100) * 32768 + (t 模 32768)
结果<- 32768 * (u div 100) + (v div 100)
澄清 准确地说,TeX 不是将此例程应用于整数x=65536 n + f
,而是应用于(半字)整数n
,上面的例程还返回“余数” v mod 100
,然后将其与f
和比例适当组合7227/100
,这样几乎直到最后数据都保持形状,(N, F)
表示N + F/65536
精确值F
被截断为整数;在最后一步,attach_fraction
子例程将其放入y = 65536*N+F
寄存器中。但这个最终整数y
与上面的过程应用于完全相同x = 65536 n +f
。由于算术溢出,这不可能直接实现。
按照步骤x = 32768 q + r
,t = 7227r
,u=7227q + int(7227r/32768) = 7727x/32768 - 7227r/32768 + int(7227r/32768)
这意味着u
(是整数)=7227x/32768 - d
且0<= d < 1
。因此u = int(7227x/32768)
。记u =100*(u div 100) + (u mod 100) = 100*(RESULT/32768 - (v div 100)/32768) + (v/ 32768 - (t mod 32768)/32768) = 100*RESULT/32768 + (v mod 100)/32768 - (t mod 32768)/32768
,我们得到RESULT = x*7227/100 - 32768*d/100 - (v mod 100)/100 + (t mod 32768)/100
。但d
是t/32768 - int(t/32768)
= (t mod 32768)/32768
,事实上。因此所有简化为RESULT= x*7227/100 - (v mod 100)/100
。由于RESULT
是整数,并且x*7227
是整数,这意味着 ,确切地说RESULT
是 截断x*7227/100
为整数。
我们可以将整个事情总结为:
第一的圆形的将小数转换为的
abc.xyz..
整数倍。这样做时,我们只需保留输入的 17 位小数。x
1/65536
乘以转换因子
72.27
,然后截短为整数单位sp
。
啊,该死的,我真想说明一下cm
。那么,§458 中的转换系数就是7227/254
,上面的所有内容都100
替换为254
。
让我们这样看一下1.52400970458984374999999999999cm
。首先,我们只需要小数点后 17 位数字。计算数字,看看我们是否可以将输入简化为1.52400970458984374
。然后我们需要乘以65536
并四舍五入。选择您喜欢的引擎。有些人喜欢 Maple 等。其他人喜欢xint
。
$ rlwrap etex -jobname worksheet
This is pdfTeX, Version 3.14159265-2.6-1.40.17 (TeX Live 2016) (preloaded format=etex)
restricted \write18 enabled.
**xintexpr.sty
entering extended mode
(/usr/local/texlive/2016/texmf-dist/tex/generic/xint/xintexpr.sty
(/usr/local/texlive/2016/texmf-dist/tex/generic/xint/xintfrac.sty
(/usr/local/texlive/2016/texmf-dist/tex/generic/xint/xint.sty
(/usr/local/texlive/2016/texmf-dist/tex/generic/xint/xintcore.sty
(/usr/local/texlive/2016/texmf-dist/tex/generic/xint/xintkernel.sty))))
(/usr/local/texlive/2016/texmf-dist/tex/generic/xint/xinttools.sty))
*\def\x #1;{\message{\xinttheiexpr[40] #1\relax}}% (this rounds)
*\x 65536*1.52400970458984374;
99877.4999999999993446400000000000000000000000
*\x 65536*1.52400970458984375;
99877.5000000000000000000000000000000000000000
*
这里我们处于一个边界情况,第一种情况给出99877
。然后我们执行第二步,即99877*7227/254
:
*\x 99877*7227/254;
2841775.9015748031496062992125984251968503937008
我们必须截断它:结果是2841775sp
。
在第二种情况下,我们首先通过四舍五入得到99878
,然后我们必须评估99878*7227/254
:
*\x 99878*7227/254;
2841804.3543307086614173228346456692913385826772
因此结果是2841804sp
。
现在我们来看看规范的情况0.6 in
。我们重复上面的操作。首先0.6*65536=39321.6
将 舍入为39322
。然后39322*7227/100 = 2841800.94
将 截断为2841800sp
。
您将在下面找到所有这些值。
记录显示1.4in
:1.4*65536=91750.4
,四舍五入为,91750
然后91750*7227/100=6630772.5
截断为6630772sp
。
这不是一个答案,但对于评论来说太长了
您cm
当时使用的是尺寸单位吗?
编辑我认为你正在使用0.6in
。请参见底部。
cm
作为尺寸单位存在(目前令我感到惊讶,因为我已经完全忘记了尺寸的 TeX 输入过程的细节)敏感性。
{
\dimen2=1.52400970458984374999999999999cm
\number\dimen2
\dimen2=1.52400970458984375cm
\number\dimen2
\dimen2=1.52400970458984374cm
\number\dimen2
}
\input xintexpr.sty
\xinttheiexpr [50] 1.52400970458984374999999999999*72.27/2.54*65536\relax
\xinttheiexpr [50] 1.52400970458984375*72.27/2.54*65536\relax
\xinttheiexpr [50] 1.52400970458984374*72.27/2.54*65536\relax
\bye
更新:
{
\dimen2=1.52400970458984374999999999999cm
\number\dimen2
\dimen2=1.52400970458984375cm
\number\dimen2
\dimen2=1.52400970458984374cm
\number\dimen2
}
\input xintexpr.sty
\xinttheiexpr [50] 1.52400970458984374999999999999*72.27/2.54*65536\relax
\xinttheiexpr [50] 1.52400970458984375*72.27/2.54*65536\relax
\xinttheiexpr [50] 1.52400970458984374*72.27/2.54*65536\relax
\number\dimexpr 2.54cm\relax
\number\dimexpr 1in\relax
\number\dimexpr 254cm\relax
\number\dimexpr 100in\relax
\xinttheiexpr [50] 1.52400970458984374/2.54\relax
{
\dimen2=0.6in
\number\dimen2
}
\bye
% TeX value
{
\dimen2=0.6in
\number\dimen2
}
% exact value:
\xinttheiexpr [10] 0.6*72.27*65536\relax
\bye