4

为什么计算器 -1 mod 26 = 25,但在 C 或 Java-1 % 26 == -1中。我需要一个像计算器一样解决它的程序。两者有区别吗?

4

3 回答 3

6

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

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

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

哪里floor()是向负无穷大舍入。

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

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

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

其中integerpart()与 (float -> integer) 强制转换相同。(向零舍入)

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

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

于 2011-09-20T02:49:25.950 回答
5

“怎么会 ... ?”

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

事实上,关于模运算的 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));
于 2011-09-20T02:50:48.913 回答
3

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

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

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

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

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

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

另外,请注意,在 JLS 中权威地描述了 Java 的结果应该是什么:在第 15.17.3 节 - 余数运算符 % 中。他们在那里给出了一个动机(a%b 应该使得 (a/b)*b+(a%b) 等于 a),但正是在 JLS 中包含了该部分才使得结果如此。

于 2011-09-20T02:52:36.677 回答