How does java do modulus calculations with negative numbers?
Asked Answered
O

15

108

Am I doing modulus wrong? Because in Java -13 % 64 evaluates to -13 but I want to get 51.

Opinionated answered 9/12, 2010 at 21:57 Comment(11)
Is this a math question, or a programming question? If it's a programming question, you should share code.Ology
@Dan Even without a static main void ... I see code.Stockish
I get -13 & 64 == -13Batik
How is it you are getting 51 ratehr than -13.Northington
You aren't doing modulus at all. There is no modulo operator in Java. % is a remainder operator.Apt
remainder is never negative, basic math concept. you will have to subastratct denom from outputSundry
I don't know how you're getting a positive number. Given the expression x % y, A) if x is negative the remainder is negative, ie x % y == -(-x % y). B) the sign of y has no effect ie x % y == x % -ySumptuous
Confusing question: Java 8 gives -13, as some other people say. Which Java version did you supposedly get that with?Cornetist
Related: Best way to make Java's modulus behave like it should with negative numbersCockeye
I've checked the original question wording, where the author said "I keep getting -13 % 64 = -13 not -13 % 64 = 51" which is the opposite of what this question became after series of edits. So I've restored the original meaning.Extradite
Same thing, but for JavaScript: JavaScript % (modulo) gives a negative result for negative numbersApis
N
112

Both definitions of modulus of negative numbers are in use - some languages use one definition and some the other.

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;
}

Likewise 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;
}
Nephron answered 9/12, 2010 at 22:0 Comment(4)
This doesn't work good if n is negative. If you user same example from Java 7 Lang Spec (Section 15.17.3): (-5) % (-3) = -2. Adding -3 will not work. You should add absolute value of n if you want to be sure that value is positive.Bautzen
In Java negative modulo does not change anything, if you use an Abs() anyway, just write r = x % abs(n). I don't like if statement, I'd rather write r = ((x%n) + n) % n. Concerning power of 2 modulo (2,4,8,16,etc..) and positive answer, consider binary mask r = x & 63.Ruler
In the context of Java (as per question tag) this answer is essentially "wrong". Given the expression x % y, A) if x is negative the remainder is negative, ie x % y == -(-x % y). B) the sign of y has no effect ie x % y == x % -ySumptuous
Without opening a new question, and for people landing on this page while Googling for C and C++ % (myself included), I'd like to point out that the same rules also apply to C and C++.Apis
M
78

Since "mathematically" both are correct:

-13 % 64 = -13 (on modulus 64)  
-13 % 64 = 51 (on modulus 64)

One of the options had to be chosen by Java language developers and they chose:

the sign of the result equals the sign of the dividend.

Says it in Java specs:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3

Mezzosoprano answered 9/12, 2010 at 21:58 Comment(5)
The question is "why does Java give me -13 % 64 = 51 when I was expecting -13?".Gearldinegearshift
@pascal: java gives you the right definition in math and the way it has been implemented to do that not the thing you expecting from it.Myrnamyrobalan
The mathematically sane behavior is available in Java 8: Math.floorModEupatorium
Something in their 15.17.3. Remainder Operator % examples isn't clear. int result = (-5) % 3; gives -2. int result = (-3) % 5; gives -3. In general, int result = (-a) % b; gives the right answer when |-a| > b. In order to get the proper result when |-a| < b we should wrap the divisor. int result = ((-a) % b) + b; for negative a or int result = (((-a) % b) + b) % b; for positive or negative aPandit
@Mezzosoprano I didn't understand this, How could both be same?Defrayal
G
22

Are you sure you are working in Java? 'cause Java gives -13 % 64 = -13 as expected. The sign of dividend!

Grindstone answered 9/1, 2011 at 10:44 Comment(0)
R
14

Note that this answer was for a previous, different version of the question.

Your result is wrong for Java. Please provide some context how you arrived at it (your program, implementation and version of Java).

From the Java Language Specification

15.17.3 Remainder Operator %
[...]
The remainder operation for operands that are integers after binary numeric promotion (§5.6.2) produces a result value such that (a/b)*b+(a%b) is equal to a.
15.17.2 Division Operator /
[...]
Integer division rounds toward 0.

Since / is rounded towards zero (resulting in zero), the result of % should be negative in this case.

Reproval answered 10/12, 2010 at 20:34 Comment(3)
Something in their 15.17.3. Remainder Operator % examples isn't clear. int result = (-5) % 3; gives -2 int result = (-3) % 5; gives -3 In general, int result = (-a) % b; gives the right answer when |-a| > b In order to get the proper result when |-a| < b we should wrap the divisor. int result = ((-a) % b) + b; for negative a or int result = (((-a) % b) + b) % b; for positive or negative a.Pandit
Your comment is quite unclear. The section defines the correct result, and the examples agree with that definition. For your example (-3) % 5 the correct result according to the definition is -3, and a correct implementation of Java should produce that result.Reproval
I guess I didn't explain myself correctly. What I meant by "the right answer" when |-a|<b is that in order to get a positive result we should "wrap" the given result from a%b by adding b to it. In my example, (-3)%5 indeed gives -3, and if we want the positive remainder we should add 5 to it, and then the result will be 2Pandit
D
6

you can use

(x % n) - (x < 0 ? n : 0);
Diplopia answered 9/12, 2010 at 22:5 Comment(3)
@Diplopia You can also do: ((x % k) + k) % k. (Though yours is probably more readable.)Reavis
@JohnKurlak You version works like this: 4 % 3 = 1 OR 4 % -3 = -2 OR -4 % 3 = 2 OR -4 % -3 = -1 but the one from ruslik works like this: 4 % 3 = 1 OR 4 % -3 = 1 OR -4 % 3 = -4 OR -4 % -3 = 2Louden
@Louden Thanks for pointing this out. My code is helpful for when you want the modulus result to be in the range of [0, sign(divisor) * divisor) instead of [0, sign(dividend) * divisor).Reavis
G
3

Your answer is in wikipedia: modulo operation

It says, that in Java the sign on modulo operation is the same as that of dividend. and since we're talking about the rest of the division operation is just fine, that it returns -13 in your case, since -13/64 = 0. -13-0 = -13.

EDIT: Sorry, misunderstood your question...You're right, java should give -13. Can you provide more surrounding code?

Gnotobiotics answered 9/12, 2010 at 22:6 Comment(0)
E
2

Modulo arithmetic with negative operands is defined by the language designer, who might leave it to the language implementation, who might defer the definition to the CPU architecture.

I wasn't able to find a Java language definition.
Thanks Ishtar, Java Language Specification for the Remainder Operator % says that the sign of the result is the same as the sign of the numerator.

Ergosterol answered 9/12, 2010 at 22:2 Comment(0)
M
1

x = x + m = x - m in modulus m.
so -13 = -13 + 64 in modulus 64 and -13 = 51 in modulus 64.
assume Z = X * d + r, if 0 < r < X then in division Z/X we call r the remainder.
Z % X returns the remainder of Z/X.

Myrnamyrobalan answered 9/12, 2010 at 22:2 Comment(0)
P
1

To overcome this, you could add 64 (or whatever your modulus base is) to the negative value until it is positive

int k = -13;
int modbase = 64;

while (k < 0) {
    k += modbase;
}

int result = k % modbase;

The result will still be in the same equivalence class.

Paddle answered 9/12, 2010 at 22:7 Comment(0)
O
1

The mod function is defined as the amount by which a number exceeds the largest integer multiple of the divisor that is not greater than that number. So in your case of

-13 % 64

the largest integer multiple of 64 that does not exceed -13 is -64. Now, when you subtract -13 from -64 it equals 51 -13 - (-64) = -13 + 64 = 51

Ophidian answered 9/12, 2010 at 22:9 Comment(0)
B
0

In my version of Java JDK 1.8.0_05 -13%64=-13

you could try -13-(int(-13/64)) in other words do division cast to an integer to get rid of the fraction part then subtract from numerator So numerator-(int(numerator/denominator)) should give the correct remainder & sign

Bonaventura answered 12/3, 2015 at 2:0 Comment(0)
J
0

In Java latest versions you get -13%64 = -13. The answer will always have sign of numerator.

Jeremiahjeremias answered 23/9, 2015 at 14:40 Comment(3)
In which version was this change made?Bulldog
In java 7 it clearly mentions that mod will have sign of numerator :)Jeremiahjeremias
@Bulldog It was never changed.Apt
M
0

According to section 15.17.3 of the JLS, "The remainder operation for operands that are integers after binary numeric promotion produces a result value such that (a/b)*b+(a%b) is equal to a. This identity holds even in the special case that the dividend is the negative integer of largest possible magnitude for its type and the divisor is -1 (the remainder is 0)."

Hope that helps.

Marrufo answered 14/4, 2016 at 14:9 Comment(0)
A
0

How to get only positive modulus numbers in C or C++ (since the % operator allows negative numbers)

Java and C and C++ all appear to act similarly in this manner. Without opening a new question, I'd like to present the approach for C and C++ as well.

From modulus_of_positive_and_negative_integers.c in my eRCaGuy_hello_world repo:

/// A function to perform and return the mathematical modulus as returned by
/// programming calculators and Google. In other words, it will **always**
/// return a positive value, unlike the `%` remainder operator in C!
/// Example:
/// So, `-5 % 180` in C or C++ is `-5`, but `mathematical_modulo(-5, 180)`
/// is the same as "-5 mod 180" in a calculator or on Google, and is `175`.
int mathematical_modulo(int num1, int num2)
{
    int mod = num1 % num2;
    if (mod < 0)
    {
        mod += num2;
    }

    return mod;
}

Sample tests of the code above:

Notice that -10 % 180 produces -10 in C and C++ since the % operator acts like a simple remainder, not a roll-over modulo, whereas mathematical_modulo(-10, 180) produces 170, since the underflow wraps back around to the max value of 180 in this case, and then down 10 steps again.

printf("-10 %% 180 = %4i\n", -10 % 180);
printf("  0 %% 180 = %4i\n",   0 % 180);
printf(" 10 %% 180 = %4i\n",  10 % 180);
printf("\n");

printf("mathematical_modulo(-10, 180) = %4i\n",
        mathematical_modulo(-10, 180));
printf("mathematical_modulo(  0, 180) = %4i\n",
        mathematical_modulo(  0, 180));
printf("mathematical_modulo( 10, 180) = %4i\n",
        mathematical_modulo( 10, 180));
printf("\n");

Sample output:

-10 % 180 =  -10
  0 % 180 =    0
 10 % 180 =   10

mathematical_modulo(-10, 180) =  170
mathematical_modulo(  0, 180) =    0
mathematical_modulo( 10, 180) =   10

Calculator tool on Linux

In C or C++, -10 % 180 is -10. But, on my Linux calculator, -10 mod 180 is 170:

enter image description here

Google calculator in browser

On Google, -10 % 180, or -10 mod 180 (same thing on Google) are both 170 as well:

enter image description here

References

  1. My own experimentation, learning, and self-study via my code linked-to above.
  2. JavaScript % (modulo) gives a negative result for negative numbers
  3. This answer: How does java do modulus calculations with negative numbers?
Apis answered 20/9, 2022 at 5:31 Comment(0)
P
-1

I don't think Java returns 51 in this case. I am running Java 8 on a Mac and I get:

-13 % 64 = -13

Program:

public class Test {
    public static void main(String[] args) {
        int i = -13;
        int j = 64;
        System.out.println(i % j);
    }
}
Polygraph answered 23/6, 2014 at 15:15 Comment(4)
@XaverKapeller, no ! Many people pointed out that mathematically speaking -13 and 51 are correct. In Java, -13 is the expected answer, and it's what I got too, so I don't know how submitter got 51, it's mystery. Mode details about the context could help to answer correctly this question.Ruler
@Xaver Kapeller: How can 51 and -13 both can be correct ? Java would return just one value ..Polygraph
@XaverKapeller How can an answer that documents what Java actually does possibly be wrong?Apt
@EJP I think 3 years ago when I wrote this I was dumb enough to value mathematical accuracy more than the simple reality of how java deals with this. Thanks for reminding me to remove my stupid comment :DLustrate

© 2022 - 2024 — McMap. All rights reserved.