Modulo operation with negative numbers

前端 未结 12 1423
旧巷少年郎
旧巷少年郎 2020-11-22 06:10

In a C program i was trying the below operations(Just to check the behavior )

 x = 5 % (-3);
 y = (-5) % (3);
 z = (-5) % (-3); 

printf(\"%d ,%d ,%d\", x, y         


        
相关标签:
12条回答
  • 2020-11-22 06:46

    According to C99 standard, section 6.5.5 Multiplicative operators, the following is required:

    (a / b) * b + a % b = a
    

    Conclusion

    The sign of the result of a remainder operation, according to C99, is the same as the dividend's one.

    Let's see some examples (dividend / divisor):

    When only dividend is negative

    (-3 / 2) * 2  +  -3 % 2 = -3
    
    (-3 / 2) * 2 = -2
    
    (-3 % 2) must be -1
    

    When only divisor is negative

    (3 / -2) * -2  +  3 % -2 = 3
    
    (3 / -2) * -2 = 2
    
    (3 % -2) must be 1
    

    When both divisor and dividend are negative

    (-3 / -2) * -2  +  -3 % -2 = -3
    
    (-3 / -2) * -2 = -2
    
    (-3 % -2) must be -1
    

    6.5.5 Multiplicative operators

    Syntax

    1. multiplicative-expression:
      • cast-expression
      • multiplicative-expression * cast-expression
      • multiplicative-expression / cast-expression
      • multiplicative-expression % cast-expression

    Constraints

    1. Each of the operands shall have arithmetic type. The operands of the % operator shall have integer type.

    Semantics

    1. The usual arithmetic conversions are performed on the operands.

    2. The result of the binary * operator is the product of the operands.

    3. The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.

    4. When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded [1]. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.

    [1]: This is often called "truncation toward zero".

    0 讨论(0)
  • 2020-11-22 06:47

    Can a modulus be negative?

    % can be negative as it is the remainder operator, the remainder after division, not after Euclidean_division. Since C99 the result may be 0, negative or positive.

     // a % b
     7 %  3 -->  1  
     7 % -3 -->  1  
    -7 %  3 --> -1  
    -7 % -3 --> -1  
    

    The modulo OP wanted is a classic Euclidean modulo, not %.

    I was expecting a positive result every time.

    To perform a Euclidean modulo that is well defined whenever a/b is defined, a,b are of any sign and the result is never negative:

    int modulo_Euclidean(int a, int b) {
      int m = a % b;
      if (m < 0) {
        // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
        m = (b < 0) ? m - b : m + b;
      }
      return m;
    }
    
    modulo_Euclidean( 7,  3) -->  1  
    modulo_Euclidean( 7, -3) -->  1  
    modulo_Euclidean(-7,  3) -->  2  
    modulo_Euclidean(-7, -3) -->  2   
    
    0 讨论(0)
  • 2020-11-22 06:48

    Based on the C99 Specification: a == (a / b) * b + a % b

    We can write a function to calculate (a % b) == a - (a / b) * b!

    int remainder(int a, int b)
    {
        return a - (a / b) * b;
    }
    

    For modulo operation, we can have the following function (assuming b > 0)

    int mod(int a, int b)
    {
        int r = a % b;
        return r < 0 ? r + b : r;
    }
    

    My conclusion is that a % b in C is a remainder operation and NOT a modulo operation.

    0 讨论(0)
  • 2020-11-22 06:50

    C99 requires that when a/b is representable:

    (a/b) * b + a%b shall equal a

    This makes sense, logically. Right?

    Let's see what this leads to:


    Example A. 5/(-3) is -1

    => (-1) * (-3) + 5%(-3) = 5

    This can only happen if 5%(-3) is 2.


    Example B. (-5)/3 is -1

    => (-1) * 3 + (-5)%3 = -5

    This can only happen if (-5)%3 is -2

    0 讨论(0)
  • 2020-11-22 06:54

    The other answers have explained in C99 or later, division of integers involving negative operands always truncate towards zero.

    Note that, in C89, whether the result round upward or downward is implementation-defined. Because (a/b) * b + a%b equals a in all standards, the result of % involving negative operands is also implementation-defined in C89.

    0 讨论(0)
  • 2020-11-22 06:54

    It seems the problem is that / is not floor operation.

    int mod(int m, float n)
    {  
      return m - floor(m/n)*n;
    }
    
    0 讨论(0)
提交回复
热议问题