为什么 \numexpr 整数除法会四舍五入而不是截断?

为什么 \numexpr 整数除法会四舍五入而不是截断?

在我使用 的\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

这样人们就总是知道所用的部门是什么。

相关内容