12

I am curious about these languages (Java, C ...) which ignore mathematical definition of modulus operation.

What is the point of returning negative values in a module operation (that, by definition, should allways return a positive number)?

eversor
  • 3,031
  • 2
  • 26
  • 46
  • 12
    There is no definition that says that anything should be "allways positive". Modular arithmetic is about equivalence classes, and any representative is as good as any other. – Kerrek SB Nov 29 '11 at 22:43
  • 1
    @OliCharlesworth: Does C99 specify any constraints on modulo arithmetic? – Matt Joiner Nov 29 '11 at 22:46
  • 2
    It would be _nice_ to have a modulus operation that produced canonical representatives, though. – hmakholm left over Monica Nov 29 '11 at 22:48
  • 1
    @Matt: Yes, implicitly. It mandates that `(a/b)*b + a%b == a`, and that division truncates towards zero. – Oliver Charlesworth Nov 29 '11 at 22:48
  • 2
    @KerrekSB the problem here is that negative numbers fall into different equivalence classes than positive ones, unlike mathematical modulus. – soulcheck Nov 29 '11 at 22:48
  • it's ridiculous that something as simple as this does not have a defined behaviour in such a major programming language. You can't use abs(a % b) because some implementations mirror at 0, some don't. And you end up pulling stuff like ((a % b) + b) % b and that weird sensation, when it's going to break. – pezcode Nov 29 '11 at 22:53
  • @pez: It's not ridiculous. C was originally written to reflect the reality of the platforms it was run on. I'm not sure I understand your examples... – Oliver Charlesworth Nov 29 '11 at 22:54
  • @Oli, -7 % 3 can be 2 or -2 or even -1, depending on the compiler. What use is that result if I can't be sure which it will be? – pezcode Nov 29 '11 at 22:56
  • @pezcode: There are only two possible answers. To answer your question: you shouldn't be writing programs in pre-C99 that rely on it, just like you shouldn't be writing programs that depend on specific behaviour of `/`. – Oliver Charlesworth Nov 29 '11 at 22:59
  • 1
    @soulcheck: I think that statement has to be made more precise: The remainder of dividing *n* by 3 is a representative for the residue class of *n*, and the remainder of dividing *n* by -3 is a representative for the class of - *n*. However, any representative is still as good as any other in terms of modular arithmetic. (Hence it's better to think of "remainder" than of "modulo", in the sense of `(a / b) * b + (a % b) == a`.) – Kerrek SB Nov 29 '11 at 23:07
  • 1
    What (GMT) time of day was (time_t)(-10000)? If you answered 21:13:20 instead of -2:-46:-40, then you'll probably like Python's definition of `%` better than C99's. – dan04 Nov 29 '11 at 23:07
  • @dan04: Maybe. But I bet it's possible to find a different example where C99's definition is the more useful one. – Oliver Charlesworth Nov 29 '11 at 23:25
  • @KerrekSB Well in my maths classes "modulus" was also used for the magnitude of a complex number (which is nonnegative) and I've yet to see anyone in congruence theory who assumes that the modulus may be negative. So there are some precedents there ;) Personally I think it's generally the more intuitive solution to have the modulus nonnegative, but I agree that there's no universal agreement on this. Heck even Knuth (who certainly has quite the mathematical background) defined the mod in a way that it could be negative. – Voo Nov 29 '11 at 23:32
  • 1
    @Voo: Come on, you know better than to through the *other* modulus (i.e. absolute value) in here to watch the shrapnel fly. Nobody was confused about that! :-) – Kerrek SB Nov 29 '11 at 23:35
  • @Kerrek Oh but I felt so clever about that little nitpick ;) I mean in the end I still think it's less intuitive to have a negative modulo, but it hasn't caused me any sleepless nights - just one more thing you have to remember. – Voo Nov 29 '11 at 23:49

6 Answers6

8

In Java at least, it's not a modulus operator - it's a remainder operator.

I believe the reason for it being chosen that way is to make this relation work (from the JLS):

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. 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). It follows from this rule that the result of the remainder operation can be negative only if the dividend is negative, and can be positive only if the dividend is positive; moreover, the magnitude of the result is always less than the magnitude of the divisor.

That equality relation seems like a reasonable thing to use as part of the definition. If you take division truncating towards zero to be a given, that leaves you with a negative remainder.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @JerryCoffin: Yes, but in conjunction with division truncating to 0, you end up with that. I'll add the bit about division to my answer. – Jon Skeet Nov 29 '11 at 23:02
  • The same is broadly true in C99: the operator has no name other than `%`, but its result is *"the remainder"*; and the same euclidean relation between `a` and `b` is true (except that C does not have the special case for `INT_MIN % -1` - that is undefined behaviour). – caf Nov 29 '11 at 23:07
  • @caf: where do you find anything saying `INT_MIN % -1` gives UB? I don't see that anywhere in either the C or C++ standards. – Jerry Coffin Nov 29 '11 at 23:13
  • 2
    @JerryCoffin: Actually I believe you are right - `INT_MIN / -1` *may* be undefined due to integer overflow but it seems like the remainder should still be zero. However I can get `gcc` to `SIGFPE` with that operation... – caf Nov 29 '11 at 23:22
  • @JerryCoffin: It seems that [R. and Jens have been here before us](http://stackoverflow.com/q/5925045/134633) - the current draft standard now explicitly calls it out as undefined behaviour. – caf Nov 29 '11 at 23:26
  • The reason you gave only makes sense because division is also defined in the wrong way. Division should always "round down" rather than "round towards zero". – R.. GitHub STOP HELPING ICE Nov 29 '11 at 23:27
  • @caf: Yes, but that just says the *value* is undefined. Undefined Behavior is a *whole* different story. – Jerry Coffin Nov 29 '11 at 23:28
  • @JerryCoffin: I'm not sure which comment you're referring to - `INT_MIN / -1` is definitely undefined behaviour due to signed integer overflow, just like `INT_MAX + 1` is. The new language in the draft referring to the `%` operator specifically says the *behaviour* is undefined. – caf Nov 30 '11 at 00:14
  • @caf: I was referring to the last preceding comment, but `INT_MIN/-1` isn't necessarily undefined. It'll give UB in 2's complement, but not sign/magnitude or 1's complement (for both of them, INT_MIN/-1 == INT_MAX). The only situation in which I can see C99 or N3290 saying % gives UB is if the second operand is 0 (C99: §6.5.5/5, N3290: §5.6/4). – Jerry Coffin Nov 30 '11 at 00:23
  • @JerryCoffin: Yes, I do mean *potential* UB there, so it is more akin to `-INT_MAX - 1` in that respect. WRT to `%` it is [N1548](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf) that includes the language explicitly making the behaviour of both `a/b` and `a%b` undefined if `a/b` is not representable. – caf Nov 30 '11 at 00:38
  • @caf: Ah, I hadn't considered the new C draft -- I'm still too busy trying to relearn C++ to spend much time on it. – Jerry Coffin Nov 30 '11 at 00:40
6

From Wikipedia (my emphasis):

Given two positive numbers, a (the dividend) and n (the divisor), a modulo n (abbreviated as a mod n) can be thought of as the remainder, on division of a by n. For instance, the expression "5 mod 4" would evaluate to 1 because 5 divided by 4 leaves a remainder of 1, while "9 mod 3" would evaluate to 0 because the division of 9 by 3 leaves a remainder of 0; there is nothing to subtract from 9 after multiplying 3 times 3. (Notice that doing the division with a calculator won't show you the result referred to here by this operation, the quotient will be expressed as a decimal.) When either a or n is negative, this naive definition breaks down and programming languages differ in how these values are defined. Although typically performed with a and n both being integers, many computing systems allow other types of numeric operands. The range of numbers for an integer modulo of n is 0 to n - 1. (n mod 1 is always 0; n mod 0 is undefined, possibly resulting in a "Division by zero" error in computer programming languages) See modular arithmetic for an older and related convention applied in number theory.

Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
  • Mathematically, the integer remainder is always in the range of 0 to one less than the divisor, assuming a positive divisor. This conflicts with the ugly definition programming languages (and cpus) tend to use. The former definition is extremely useful, e.g. for date computations. The latter is useless except when using integers as approximations for non-integral values (e.g. fixed point). – R.. GitHub STOP HELPING ICE Nov 29 '11 at 23:25
  • @R..: I wouldn't say "mathematically" (unless you have some genuine theory to back this up), but rather "conventionally". (For positive dividends, this is only relevant for negative divisors of course.) – Kerrek SB Nov 29 '11 at 23:27
  • 2
    Well the algebraic definition of division `n/d` I always learned was `n=qd+r` where `0≤r – R.. GitHub STOP HELPING ICE Nov 29 '11 at 23:34
  • @R..: actually, that's a good point -- it's still just convention, but that's the popular way the division theorem is stated. (Though note that the theorem is equally valid for any other fixed choice of coset.) That said, this is a nice argument in favour of fixing the remainder to be positive. – Kerrek SB Nov 29 '11 at 23:57
6

I doubt that the remainder operator was deliberately designed to have those semantics, which I agree aren't very useful. (Would you ever write a calendar program that shows the weekdays Sunday, Anti-Saturday, Anti-Friday, ..., Anti-Monday for dates before the epoch?)

Rather, negative remainders are a side effect of the way integer division is defined.

A rem B := A - (A div B) * B

If A div B is defined as trunc(A/B), you get C's % operator. If A div B is defined as floor(A/B), you get Python's % operator. Other definitions are possible.

So, the real question is:

Why do C++, Java, C#, etc. use truncating integer division?

Because that's the way that C does it.

Why does C use truncating division?

Originally, C didn't specify how / should handle negative numbers. It left it up to the hardware.

In practice, every significant C implementation used truncating division, so in 1999 these semantics were formally made a part of the C standard.

Why does hardware use truncating division?

Because it's easier (=cheaper) to implement in terms of unsigned division. You just calculate abs(A) div abs(B) and flip the sign if (A < 0) xor (B < 0).

Floored division has the additional step of subtracting 1 from the quotient if the remainder is nonzero.

dan04
  • 87,747
  • 23
  • 163
  • 198
  • I wonder for what applications the C99 version of signed division is actually useful? In my experience, in cases which require exactitude, I almost always have to handle negative numbers specially, so having divisions involving negative numbers return unspecified values wouldn't be much less useful than having them behave as the standard dictates. I could see an argument for leaving the behavior unspecified (which could speed things up on hardware which lacks a signed division instruction), but not much advantage to the standard as written. – supercat Jun 19 '13 at 21:39
3

Most of them are not defined to return a modulus. What they're defined to return is a remainder, for which positive and negative values are equally reasonable.

In C or C++ it's pretty reasonable to say it should produce whatever the underlying hardware produces. That excuse/reason doesn't work nearly as well for Java though.

Also note that in C89/90 and C++98/03, the remainder could be either positive or negative, as long as the results from remainder and division worked together ((a/b)*b+a%b == a). In C99 and C++11, the rules been tightened up so the division must truncate toward zero, and if there is a remainder it must be negative.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

A pragmatic reason to return a negative value for modulus would be that the hardware instruction implementing modulus does so.

So standards leave that ill defined, so that compilers can do whatever is simpler to them.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

In neither of the C or Java standards is % referred to as a modulus operator - rather, it returns the remainder.

It is defined to return negative numbers for negative dividends so that the relation (a/b)*b + a%b == a holds, as long as a / b is representable. Since the division operator is defined to truncate towards zero, this constrains the sign of the remainder.

caf
  • 233,326
  • 40
  • 323
  • 462