在我使用 的\numexpr
整数除法/
时,我从未从它四舍五入而不是截断的事实中获得任何优势。TeX
自己的\divide
截断。
如果我们处理的是浮点数,我可以理解。但这里的操作是针对整数的。同样,每当这在编码中成为我的问题时,总是系统地“舍入”是一件麻烦事,并生成额外的编码来解决这个问题。
有什么理由认为四舍五入比截断更可取吗?
说实话,我必须报告,终于一我利用舍入功能的场合:在\xintDSRr
的宏中xint 1.2i (2016/12/13)
。这是一个宏,它给定一个(长)整数N
,计算N/10
从零开始舍入(即,它将 的扩展N/10
为\numexpr
大整数)。该宏主要用于内部使用,\xintiiDivRound
它是通用宏,用于计算舍入为一般(大)分数的整数N/M
。在 的所有数千行中xint
,有无数次使用\numexpr
,我认为这是唯一让我感到高兴的地方,运算/
符在 内部舍入\numexpr
。考虑到这些宏的作用,这并不奇怪!
关于不好经历的确认,但我现在忘记了确切的细节,我认为我曾经特别恼火,因为在执行“缩放”操作时,a*b/c
乘积可以是双字而不会引起算术溢出,c
但除法是四舍五入的。我想我想用它来计算十的幂,如果它被截断,我可以加快一些核心算法的速度xint
,但我只在记忆中留下了短暂的感觉,我忘记了细节。
答案1
这是相关部分etex.ch
:
5247 @ The function |quotient(n,d)| computes the rounded quotient
5248 $q=\lfloor n/d+{1\over2}\rfloor$, when $n$ and $d$ are positive.
5249
5250 @<Declare subprocedures for |scan_expr|@>=
5251 function quotient(@!n,@!d:integer):integer;
5252 var negative:boolean; {should the answer be negated?}
5253 @!a:integer; {the answer}
5254 begin if d=0 then num_error(a)
5255 else begin if d>0 then negative:=false
5256 else begin negate(d); negative:=true;
5257 end;
5258 if n<0 then
5259 begin negate(n); negative:=not negative;
5260 end;
5261 a:=n div d; n:=n-a*d; d:=n-d; {avoid certain compiler optimizations!}
5262 if d+n>=0 then incr(a);
5263 if negative then negate(a);
5264 end;
5265 quotient:=a;
5266 end;
5267
5268 @ Here the term |t| is multiplied by the quotient $n/f$.
5269
5270 @d expr_s(#)==#:=fract(#,n,f,max_dimen)
5271
5272 @<Cases for evaluation of the current term@>=
5273 expr_scale: if l=int_val then t:=fract(t,n,f,infinity)
5274 else if l=dimen_val then expr_s(t)
5275 else begin expr_s(width(t)); expr_s(stretch(t)); expr_s(shrink(t));
5276 end;
5277
5278 @ Finally, the function |fract(x,n,d,max_answer)| computes the integer
5279 $q=\lfloor xn/d+{1\over2}\rfloor$, when $x$, $n$, and $d$ are positive
5280 and the result does not exceed |max_answer|. We can't use floating
5281 point arithmetic since the routine must produce identical results in all
5282 cases; and it would be too dangerous to multiply by~|n| and then divide
5283 by~|d|, in separate operations, since overflow might well occur. Hence
5284 this subroutine simulates double precision arithmetic, somewhat
5285 analogous to \MF's |make_fraction| and |take_fraction| routines.
5286
5287 @d too_big=88 {go here when the result is too big}
为什么 Peter Breitenlohner 决定舍入而不是截断并没有得到解释。NTS 小组可能已经讨论过这个问题。类似的操作会产生不同的结果,这确实很麻烦。
无论如何,该行为都有明确记录etex_man.tex
:
454 The arithmetic performed by \eTeX's expressions does not do much that could
455 not be done by \TeX's arithmetic operations \|\advance|, \|\multiply|, and
456 \|\divide|, although there are some notable differences: Each factor is
457 checked to be in the allowed range, numbers must be less than $2^{31}$ in
458 absolute value, dimensions or glue components must be less than
459 $2^{14}$\[pt], \[mu], \[fil], etc.\ respectively. The arithmetic operations
460 are performed individually, except for `scaling' operations (a
461 multiplication immediately followed by a division) which are performed as
462 one combined operation with a 64-bit product as intermediate value. The
463 result of each operation is again checked to be in the allowed range.
464 Finally the results of divisions and scalings are rounded, whereas \TeX's
465 \|\divide| truncates.
在expl3
那里
\int_div_round:nn
\int_div_truncate:nn
这样人们就总是知道所用的部门是什么。