Is there a reason some languages allow a negative modulus?

元气小坏坏 提交于 2019-12-01 15:40:19

问题


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)?


回答1:


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.




回答2:


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.




回答3:


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.




回答4:


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.




回答5:


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.




回答6:


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.



来源:https://stackoverflow.com/questions/8318791/is-there-a-reason-some-languages-allow-a-negative-modulus

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!