Truncated division And Euclidean division

Mar 29, 20232 min read

之前一直不太理解 rust 语言中原始类型中的数值类型取模运算(mod)和除运算(division)单独提供 rem_eucliddiv_euclid 的原因。

数学定义:

q,rZa=nq+rr<n{\displaystyle {\begin{aligned}&q,r\in \mathbb {Z} \\&a=nq+r\\&|r|<|n|\end{aligned}}}

在编程语言中,实现除运算根据运算取整的时候采用何种策略来区分有五种实现。

  • Truncated division

    q=[an]{\displaystyle q=\left[{\frac {a}{n}}\right]} r=an[an]{\displaystyle r=a-n\left[{\frac {a}{n}}\right]}

    ![red:quotient(](/content_images/red:quotient(__ed4d56b0-1c18-4163-9c1c-5d33c482b888.png)

  • Floored division

    q=an{\displaystyle q=\left\lfloor {\frac {a}{n}}\right\rfloor } r=anan{\displaystyle r=a-n\left\lfloor {\frac {a}{n}}\right\rfloor}

    ![red:quotient(](/content_images/red:quotient(__874e6b99-28ce-47aa-9036-4852798c86c8.png)

  • Euclidean division

    q=sgn(n)an={anif n>0anif n<0{\displaystyle q=\operatorname {sgn}(n)\left\lfloor {\frac {a}{\left|n\right|}}\right\rfloor ={\begin{cases}\left\lfloor {\frac {a}{n}}\right\rfloor &{\text{if }}n>0\\\left\lceil {\frac {a}{n}}\right\rceil &{\text{if }}n<0\\\end{cases}}} r=anan{\displaystyle r=a-|n|\left\lfloor {\frac {a}{\left|n\right|}}\right\rfloor }
    • sgn 表示符号函数。

    • ⌊⌋ 表示 rounding down,向负无穷方向取整。

    • ⌈⌉ 表示 rounding up,向正无穷方向取整。

      red:quotient_

  • Rounded division

    q=round(an){\displaystyle q=\operatorname {round} \left({\frac {a}{n}}\right)} r=anround(an){\displaystyle r=a-n\operatorname {round} \left({\frac {a}{n}}\right)}

    red:quotient_

  • Ceiled division

    q=an{\displaystyle q=\left\lceil {\frac {a}{n}}\right\rceil } r=anan{\displaystyle r=a-n\left\lceil {\frac {a}{n}}\right\rceil }
    • ⌈⌉ 表示 rounding up,向正无穷方向取整。

      red:quotient_

我常用的语言中:

  • rust 的 remdiv 采用的 Truncated division 实现方案。
  • rust 的 rem_eucliddiv_euclid 采用的 Euclidean division 实现方案。
  • javascript 的 rem( % )div ( / )采用的 Truncated division 实现方案。

Reference