奇思妙想 · 2024年 4月 27日 0

求余或求模有负数参与, 不同语言结果不同?

123 次浏览

不止是除法,求余或求模一旦有负数参与,结果可能都有差异。本质在于不同语言使用不同求余规则。

  • 向零取整
    向 0 方向取最接近精确值的整数,C/ObjC/C++/Rust/C#/Java/Go/Swift/JS/VB/仓颉/PHP/Kotlin 等语言都采用这种方式。
    • 按此规则,被求模的数值是负数,求模的数值也是负数。
  • 向下取整
    向负无穷方向取最接近精确值的整数,Python采用这种方式(Python2/3都遵循)。
  • 向上取整
    向正无穷方向取最接近精确值的整数。

所以问题就简单了:

  • C语言
    9 / -4 == -2.25, 向0取整得到结果-2,推算9 % -4 == 9 - (-2 * -4) == 1.
  • Python
    9 / -4 == -2.25, 向下取整得到结果-3,推算9 % -4 == 9 - (-3 * -4) ==-3.

标准文档的规定

  • C语言C89规定,当除数和被除数有负数时,商和余数的符号是未定义行为。C99开始,此行为被约束为固定行为,即向零取整。
    • C89 6.3.5章节:"If either operand is negative. whether the result of the / operator is the
      largest integer less than or equal to the algebraic quotient or the smallest integer greater than or equal to the algebraic quotient is implementation-defined."
    • C99 6.5.5章节:"When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.”

特殊的求模

  • VB 语言用浮点数求模,会先把浮点数转换成整数再求模:
    12.5 Mod 4.6 等价于 12 Mod 4, 得到3.