为什么 expl3 的 \int_show:n 会错误地计算除法?

为什么 expl3 的 \int_show:n 会错误地计算除法?

我运行了代码

\documentclass{article}
\begin{document}
\ExplSyntaxOn
\int_new:N\l_rand
\int_step_inline:nn{50}{
  \int_set:Nn\l_rand{\int_rand:n{56}}
  \int_show:n{\l_rand+(\l_rand-1)/(8-1)}
}
\end{document}

使用 xetex。在我的日志中显示

> \l_rand +(\l_rand -1)/(8-1)=64.
<recently read> }

这很荒谬。显然 56+(56-1)/(8-1)=63,而且不可能再大了,所以这64是一个错误计算。事实上 55/7 接近 8,所以这可能是由于浮点计算错误造成的。

那么我怎样才能让 tex 避免这样的错误呢?

答案1

比较

\documentclass{article}

\begin{document}

\ExplSyntaxOn

\int_eval:n { 1/2 } \par
\int_eval:n { 55/7 } \par
\int_eval:n { \int_div_truncate:nn { 55 } { 7 } }

\ExplSyntaxOff

\end{document}

这将打印

1
8
7

因为/四舍五入到下一个整数(四舍五入到远离零的位置)。对于对称性也有\int_div_round:nn,但\int_div_round:nn { 55 } { 7 }与 相同55/7

手册中记录了这一点,我们对此无能为力,因为/根据 e-TeX 实现,这就是整数表达式中所做的。

在此处输入图片描述

这是否是一个好的选择还有待商榷,但改变这种行为是不可能的,因为 e-TeX 已经这样大约 25 年了,而一个改变会破坏大量文档。

即使使用也\fp_eval:n无法解决问题,因为你需要

\fp_eval:n { trunc(55/7,0) }

无论如何(以牺牲速度为代价)。

相关内容