Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++ output negative numbers when using modulo?

Math:

If you have an equation like this:

x = 3 mod 7 

x could be ... -4, 3, 10, 17, ..., or more generally:

x = 3 + k * 7 

where k can be any integer. I don't know of a modulo operation is defined for math, but the factor ring certainly is.

Python:

In Python, you will always get non-negative values when you use % with a positive m:

#!/usr/bin/python # -*- coding: utf-8 -*-  m = 7  for i in xrange(-8, 10 + 1):     print(i % 7) 

Results in:

6    0    1    2    3    4    5    6    0    1    2    3    4    5    6    0    1    2    3 

C++:

#include <iostream>  using namespace std;  int main(){     int m = 7;      for(int i=-8; i <= 10; i++) {         cout << (i % m) << endl;     }      return 0; } 

Will output:

-1    0    -6    -5    -4    -3    -2    -1    0    1    2    3    4    5    6    0    1    2    3     

ISO/IEC 14882:2003(E) - 5.6 Multiplicative operators:

The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined 74).

and

74) According to work underway toward the revision of ISO C, the preferred algorithm for integer division follows the rules defined in the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is always rounded toward zero.

Source: ISO/IEC 14882:2003(E)

(I couldn't find a free version of ISO/IEC 1539:1991. Does anybody know where to get it from?)

The operation seems to be defined like this:

enter image description here

Question:

Does it make sense to define it like that?

What are arguments for this specification? Is there a place where the people who create such standards discuss about it? Where I can read something about the reasons why they decided to make it this way?

Most of the time when I use modulo, I want to access elements of a datastructure. In this case, I have to make sure that mod returns a non-negative value. So, for this case, it would be good of mod always returned a non-negative value. (Another usage is the Euclidean algorithm. As you could make both numbers positive before using this algorithm, the sign of modulo would matter.)

Additional material:

See Wikipedia for a long list of what modulo does in different languages.

like image 851
Martin Thoma Avatar asked Jul 24 '12 11:07

Martin Thoma


People also ask

Why is modulo negative number?

When only the dividend is negative. If only the dividend is negative, then: Truncated modulo returns the negative remainder; and. Floored modulo returns the positive remainder.

How does modulo work with negative numbers in C?

Anyone can predict the output of a modulus operator when both operands are positive. But when it comes to the negative numbers, different languages give different outputs. In C language, modulus is calculated as, a % n = a – ( n * trunc( a/n ) ).

Does modulo return negative?

These functions give the same values for positive arguments, but the modulus always returns positive results for negative input, whereas the remainder may give negative results.

Can you use modulo with negative number?

The modulus of a negative number is found by ignoring the minus sign. The modulus of a number is denoted by writing vertical lines around the number. Note also that the modulus of a negative number can be found by multiplying it by −1 since, for example, −(−8) = 8. Exercise 1.


1 Answers

On x86 (and other processor architectures), integer division and modulo are carried out by a single operation, idiv (div for unsigned values), which produces both quotient and remainder (for word-sized arguments, in AX and DX respectively). This is used in the C library function divmod, which can be optimised by the compiler to a single instruction!

Integer division respects two rules:

  • Non-integer quotients are rounded towards zero; and
  • the equation dividend = quotient*divisor + remainder is satisfied by the results.

Accordingly, when dividing a negative number by a positive number, the quotient will be negative (or zero).

So this behaviour can be seen as the result of a chain of local decisions:

  • Processor instruction set design optimises for the common case (division) over the less common case (modulo);
  • Consistency (rounding towards zero, and respecting the division equation) is preferred over mathematical correctness;
  • C prefers efficiency and simplicitly (especially given the tendency to view C as a "high level assembler"); and
  • C++ prefers compatibility with C.
like image 93
ecatmur Avatar answered Oct 11 '22 18:10

ecatmur