【问题标题】:Why does Java's % operator give different results than my calculator for a negative dividend?为什么 Java 的 % 运算符给出的结果与我的负股息计算器不同?
【发布时间】:2011-11-20 17:26:30
【问题描述】:

计算器 -1 mod 26 = 25 怎么会用 C 或 Java -1 % 26 == -1。我需要一个像计算器一样解决它的程序。两者有区别吗?

【问题讨论】:

  • 你用的是什么计算器?从数学上讲,两个答案都是正确的。另外,在 C 语言中,我相信这里没有指定答案;它也可能是不同的值。
  • C99 要求答案为 -1。

标签: java c math modulus


【解决方案1】:

“怎么会……?”

模运算有两种常见的定义。 Java 选择了一个(“与被除数相同的符号”),计算器实现了另一个;大概是“与除数相同的符号”,尽管您需要做一些实验才能确定。

事实上,modulo operation 上的 Wikipedia 页面给出了 4 种不同的运算符定义,它们被不同的编程语言使用。 (并且一些编程语言为您提供了两个具有不同语义的运算符。)

在 C 的情况下,定义取决于您所谈论的 C 标准的版本。对于 ISO C 1999,模运算符遵循与 Java 相同的定义。对于早期版本的 C 标准,% 的语义依赖于实现

“这两者有区别吗?”

显然有!

“我需要一个像计算器一样解决问题的程序。”

随意写一篇:-)。

但是,如果您只想知道如何在 Java 中获得“与除数相同的符号”形式的模数,这里有一种方法:

int otherModulus = (a % b) + (a < 0 ? b : 0);  // works for b > 0.

int otherModulus = (a % b) +                   // works for b != 0
                   (b > 0 ? (a < 0 ? b : 0) : (a > 0 ? -b : 0));

【讨论】:

  • 你确定你的最后一个公式吗?如果 a 和 b 为负数,它给出的值低于 b。
【解决方案2】:

两个答案(25 和 -1)都是有效的。只是不同的系统有不同的约定。

我看到的最常见的(在数学中)是:

quotient  = floor(x / y)
remainder = x - quotient * y

floor() 是向负无穷舍入。

这是您的计算器提供给您的约定。 (Mathematica 也使用这种约定。)

我认为大多数编程语言使用的是:

quotient  = integerpart(x / y)
remainder = x - quotient * y

integerpart() 与 (float -> integer) 类型转换相同。 (向零舍入)

一些约定喜欢将余数与操作数之一保持相同的符号。

同样的事情也适用于分隔符的符号。不同的约定是不同的。

【讨论】:

    【解决方案3】:

    具有负操作数的模运算在不同的语言中是不同的,并且取决于要驱动的语言定义。在 Java 中,Modulus 更像是 Remainder。

    一般来说,如果你想为负输入得到一个负数,那么你可以使用这个:

    int r = x % n;
    if (r > 0 && x < 0)
    {
        r -= n;
    }
    

    或者,如果您使用的语言在负输入上返回负数并且您更喜欢正数:

    int r = x % n;
    if (r < 0)
    {
        r += n;
    }
    

    因此,根据您所需的结果,我建议您使用适当的实现,而不是依赖语言为您计算。

    另外,请注意,对于 Java 的结果应该是什么,在 JLS: in the section 15.17.3 - Remainder Operator % 中有权威性的描述。他们在那里给出了动机(a%b 应该使得 (a/b)*b+(a%b) 等于 a),但正是在 JLS 中包含该部分才使结果如此。

    【讨论】:

      猜你喜欢
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 2014-03-21
      • 1970-01-01
      • 2020-01-10
      相关资源
      最近更新 更多