Why does Java's % operator give different results than my calculator for a negative dividend?
How come on a calculator -1 mod 26 = 25, but in C or Java -1 % 26 == -1
. I need a program which solves it like the calculator. Is there a difference between the two?
Both answers (25 and -1) are valid. It's just that different systems have different conventions.
The one I see the most common (in mathematics) is:
quotient = floor(x / y)
remainder = x - quotient * y
Where floor()
is to round towards negative infinity.
This is the convention that your calculator is giving you. (Mathematica also uses this convention.)
The one I think most programming languages use is:
quotient = integerpart(x / y)
remainder = x - quotient * y
Where integerpart()
is the same as a (float -> integer) cast. (round towards zero)
Some conventions like to keep the remainder the same sign as one of the operands.
The same thing applies to the sign of the divider. Different conventions are different.
"How come ... ?"
There are two common definitions of the modulo operation. Java has chosen one ("same sign as dividend") and the calculator implements another; presumably "same sign as divisor", though you'd need to do some experiments to be sure.
In fact, the Wikipedia page on the modulo operation gives 4 different definitions of the operator that are used by different programming languages. (And some programming languages give you two operators with different semantics.)
In the case of C, the definition depends on the version of the C standard you are talking about. For ISO C 1999, the modulo operator follows the same definition as Java. For earlier versions of the C standard, the semantics of %
are implementation dependent
"Is there a difference between the two?"
Obviously there is!
"I need a program which solves it like the calculator."
Feel free to write one :-).
But if you just want to know how to get the "same sign as divisor" form of modulus in Java, here's one way:
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));
Modulo arithmetic with negative operands is different in different languages, and is upto the language definition to drive. In Java, Modulus is more like Remainder.
Generally, if you want to get a negative number for negative inputs then you can use this:
int r = x % n;
if (r > 0 && x < 0)
{
r -= n;
}
Or, if you were using a language that returns a negative number on a negative input and you would prefer positive:
int r = x % n;
if (r < 0)
{
r += n;
}
So, based on what you need as the desired result, I recommend you use the appropriate implementation rather than relying on the language to compute for you.
Also, note that what the result should be in the case of Java is described authoratively in the JLS: in the section 15.17.3 - Remainder Operator %. They give a motivation there (that a%b should be such that (a/b)*b+(a%b) is equal to a) but it is the inclusion of that section in the JLS that makes the result so.
精彩评论