4

Can someone please help me figure out why this program gives the wrong answer for a modulus operation when a negative number is entered in this C program?

I am pretty sure what is causing the problems is the scanf function. The correct answer is given when positive integers are used.

The code is below:

#include <stdio.h>

int main()
{
    int num1 = 0;
    int num2 = 0;
    int answer = 0;
    puts("enter two number to find the modulus of...");
    if (scanf("%3d %3d",&num1,&num2) != 2)
            puts("something went wrong");
    else {
            answer = (num1 % num2);
            printf("the modulus of %d and %d is: %d\n", num1, num2, answer);
    }
}
4
  • @JoachimPileborg looks like it answers some questions...the main point is that negative numbers are undefined. I am sure C can handle something this simple though; there must be some simple solution. Commented Apr 26, 2013 at 7:43
  • 1
    You would improve this question considerably if you gave some examples of the output you consider incorrect. It seems curious to blame scanf() for the answer generated by the % operator. Commented Aug 29, 2014 at 16:48
  • @Jerry Coffin The referenced Modulus with a negative number asks why C "modulus" differs from Google. The post asks why a%b is "the wrong answer for a modulus operation". IMO: This borders on either side of a duplicated post. Commented Aug 29, 2014 at 19:37
  • 1
    Can someone explain to me why the current 'duplicate' (Modulus with a negative number) is better than Does either ANSI C or ISO C specify what -5 % 10 should be?? The current duplicate was asked later, has a far lower score, and is itself closed as a duplicate of two other questions. Commented Aug 30, 2014 at 4:50

2 Answers 2

4

In ANSI C, the sign of the result of the modulus operator is not defined for negative inputs. You could try div() from the math library (ref). It returns a structure with the quotient and remainder, and it works reliably for negative inputs.

Or, as Alexey Frunze kindly suggests, you could enable C99 mode. I'm too lazy to look up the standard, but a little testing (gcc -std=c99) suggests the sign of the result matches the sign of the left operand. So div() is still best if you want ANSI compatibility.

Or, you could take total control of the situation. But you have to choose what correct means. The following is cribbed from Wikipedia.

int x, y, q, r; // all snippets: left-arg, right-arg, quotient, remainder

truncated division

q = trunc( (double)x / y);
r = x - y * q;

floored division (Knuth)

q = floor( (double)x / y);
r = x - y * q;

Euclidean division

q = y > 0 ? floor( (double)x / y) : ceiling( (double)x / y);
r = x - y * q;
Sign up to request clarification or add additional context in comments.

12 Comments

% is defined for negative integers.
@luserdroog looks like i am out of luck for negative integers. thanks all for the quick and super smart feedback.
The C standard dropped the sign "ambiguity" in 1999 (it had been allowed by the standard from 1989).
#include <stdio.h> #include <stdlib.h> int main() { int num1 = 0; int num2 = 0; div_t answer; puts("enter two number to find the modulus of..."); if (scanf("%3d %3d",&num1,&num2) != 2) puts("something went wrong"); else { answer = div(num1, num2); printf("the modulus of %d and %d is: %d\n", num1, num2,answer.rem); } return 0; }
@luserdroog see above just posted 3 seconds ahead of you :D
|
2

After accept answer

In C, since C99, the result of % is well defined even with negative operands. See below.

In C, % operator is named the "remainder" in C and not "modulus".

To perform a Euclidean division & remainder without incurring truncation, range, double conversion problems **:

void Euclidean_divide_remainder(int a, int b, int *q, int *r) {
  *q = a / b;
  *r = a % b;
  if (a < 0 && *r != 0) {
    if (b < 0) { (*q)++; *r -= b; }
    else {       (*q)--; *r += b; }
  }
}

void rtest(int a, int b) {
  int eq, er;
  Euclidean_divide_remainder(a, b, &eq, &er);
  printf("f(%2d,%2d) / %2d  %% %2d  E/ %2d  E%% %2d\n", 
      a, b, a / b, a % b, eq, er);
}

void rtest4(int a, int b) {
  rtest(a, b);
  rtest(a, -b);
  rtest(-a, b);
  rtest(-a, -b);
  printf("\n");
}

int main(void) {
  rtest4(7, 3);
  return 0;
}

f( 7, 3) /  2  %  1  E/  2  E%  1
f( 7,-3) / -2  %  1  E/ -2  E%  1
f(-7, 3) / -2  % -1  E/ -3  E%  2
f(-7,-3) /  2  % -1  E/  3  E%  2

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. C11dr §6.5.5 5

When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded. (This is often called ‘‘truncation toward zero’’.) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a; otherwise, the behavior of both a/b and a%b is undefined. C11dr §6.5.5 6

** Exceptions:

The result of a%0 is undefined.

For 2's complement, INT_MIN % -1 and INT_MIN E% -1 (which mathematically should be 0) are problems. This is caused by INT_MIN / -1 (which mathematically should be INT_MAX + 1) is a problem as the answer does not fit in the int range..

1 Comment

Interesting. I have not coded C in several months or maybe it has been over a year now! 0_o I compiled your code on my machine and ran it and obtained the same output but this example is rather confusing in my honest opinion (IMHO). I appreciate all the excitement over my c programming question though! Cool. Thanks for replying to my post guise. :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.