Page 1 of 2 12 Last
1. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Oct 2007
Posts
2
Rep Power
0

Modulus operator

Hi

I wanted some clarification regarding the way modulus operation works in C as compared to the modulus in Ruby.

For example -5%3 in C returns -2 where as the same in ruby returns 1

Why does this happen?

mathematically,
if a is divided by n, then the quotient q = floor(a/n) if n>0
and q = ceil(a/n) if n<0
and
a = n*q+r

According to the above definition, -5%3 must be 1

Thanks
2. If Ruby returns a 1, then I'd say Ruby's definition of "ceil" is messed up for negative numbers, or that "floor" should be used. Your choice.
3. No Profile Picture
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Oct 2007
Posts
921
Rep Power
540
The C standard requires that (a/b)*b + a%b will always equal a. Division always rounds towards zero

So if a is -5 and b is 3 then ...

a%b = a-(a/b)*b = -5 - (-5/3)*3 = -5 - (-1)*3 = -2
4. % returns the remainder. 3 goes into 5 one time with a remainder of 2.
5. I came across this apparent discrepancy when when modelling an algorithm in Excel and finding that its MOD() function does not work like C's % operator.

The reason is historical (inherited from FORTRAN) and technical - to do with the way computers handle integer division. I found this discussion, http://mathforum.org/library/drmath/view/52343.html where the entry by a Doctor Peterson explains this at length.

Mathematically % is the remainder operator not the modulus operator (despite being perhaps misnamed) which is not quite the same thing.

Clifford
Last edited by clifford; October 12th, 2007 at 08:46 AM. Reason: typo
6. No Profile Picture
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Oct 2007
Posts
921
Rep Power
540
Originally Posted by clifford
The reason is historical (inherited from FORTRAN) and technical - to do with the way computers handle integer division. I found this discussion, http://mathforum.org/library/drmath/view/52343.html where the entry by a Doctor Peterson explains this at length.
It's historical, but "inherited from FORTRAN" is wrong. Fortran, being a language designed with mathematical and numerical work in mind, "inherited" it from standard mathematical practice that has only been around for a few thousand years or so. I would be very surprised if Excel did it because Fortran did; a more likely explanation is that the designers of Excel took into account the need to users to do things in a more conventional mathematical way.

Originally Posted by clifford
Mathematically % is the remainder operator not the modulus operator (despite being perhaps misnamed) which is not quite the same thing.
This is true; the original designers of C were computer scientists interested in supporting programmers who want to get close to the machine. The way the % operator works happened to correspond with the way computer hardware can do things more easily.
7. No Profile Picture
Contributing User
Devshed Intermediate (1500 - 1999 posts)

Join Date
Feb 2004
Location
San Francisco Bay
Posts
1,939
Rep Power
1317
Originally Posted by An0384
Hi

I wanted some clarification regarding the way modulus operation works in C as compared to the modulus in Ruby.

For example -5%3 in C returns -2 where as the same in ruby returns 1

Why does this happen?

mathematically,
if a is divided by n, then the quotient q = floor(a/n) if n>0
and q = ceil(a/n) if n<0
and
a = n*q+r

According to the above definition, -5%3 must be 1

Thanks
The behavior of / and % with negative operands is implementation-defined. I think it usually just defaults to whatever the hardware signed division instruction does, but it isn't required to do any such thing. On the Intel architecture, that means rounding toward zero.

Edit: This post refers to C90. For C99, see below.
Last edited by Lux Perpetua; October 13th, 2007 at 03:07 PM. Reason: Correction
8. No Profile Picture
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Oct 2007
Posts
921
Rep Power
540
Originally Posted by Lux Perpetua
The behavior of / and % with negative operands is implementation-defined. I think it usually just defaults to whatever the hardware signed division instruction does, but it isn't required to do any such thing.
Rubbish.

The 1999 C standard Section 6.5.5, for example, states that;
5. 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.

6. When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded.87) If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.
And footnote 87, referred to in the above states `This is often called "truncation toward zero".'

• clifford agrees
• Lux Perpetua agrees
9. Originally Posted by LittleGrin
It's historical, but "inherited from FORTRAN" is wrong. ... I would be very surprised if Excel did it because Fortran did...
You misunderstand; that is exactly not what I said. Read the thread to which I posted a link (it is long and detailed, and requires careful reading). I was referring to C (not Excel) inheriting its behaviour from FORTRAN. In truth it is more likely that machine architecture design was determined by efficient implementation of FORTRAN and consequently many computer languages follow the most common hardware implementation (chicken-egg?). Excel uses the mathematical convention because that's its purpose (and this differs from FORTRAN). In C the fmod() function is the remainder not the modulus also. So the library designers weren't mathematicians either ;) . Efficient implementation of integer maths is not a primary goal of many more recent interpreted script languages - they are so removed from the machine architecture it would make little difference.

All that said, in all the uses I have ever had for % its behaviour is exactly the behaviour I have expected and needed. It is an integer operator - there are few applications I would suggest where a true modulus were in fact what you wanted for integer operations. However for some mathematical operations (where you would typically use floating point numbers) you may get unexpected and erroneous results from using fmod(). The solution - write your own modulo() function where it is needed. Fortran 90 for example has MODULO(a,b) being introduced as a true modulo rather than the original MOD(a,b) that is a remainder function.

Clifford
Last edited by clifford; October 13th, 2007 at 04:47 AM.
10. No Profile Picture
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Oct 2007
Posts
921
Rep Power
540
As a matter of fact, the way that C handles integer operations corresponds more closely with machine instructions than the way Fortran does it. What you say is certainly true with floating point operations. The design of early versions of Fortran and early specifications of floating point instructions in machines actually occurred very close in time - it is debatable which one came first (if, in fact, one did: it is quite possible the designers of Fortran and implementers of early floating point instruction sets worked together).

• clifford agrees : I imagine that FORTRAN was designed around an existing architecture, but that subsequent architectures prime motivation was ability to execute FORTRAN efficiently so the earlier architecture decision is reinforced.
11. Originally Posted by LittleGrin
As a matter of fact, the way that C handles integer operations corresponds more closely with machine instructions than the way Fortran does it.
Now I cannot tell if you are agreeing, disagreeing, or misinterpreting. Here is a comparison of MOD and MODULO of FORTRAN: http://www.nsc.liu.se/~boein/f77to90/a5.html#section2 MOD behaves like %. MODULO was added to FORTRAN later. Neither is incorrect, just different. MOD (like fmod and teh modulo operator in C) is misnamed however - we are stuck with it.

Clifford
12. No Profile Picture
Contributing User
Devshed Intermediate (1500 - 1999 posts)

Join Date
Feb 2004
Location
San Francisco Bay
Posts
1,939
Rep Power
1317
Originally Posted by LittleGrin
Rubbish.

The 1999 C standard Section 6.5.5, for example, states that;

And footnote 87, referred to in the above states `This is often called "truncation toward zero".'
Yes, but in the ANSI standard (which is not obsolete), the behavior is what I claim. Thanks for the correction.

In my experience, it doesn't matter if it's implementation-defined or rounds toward zero. Either way, it's an annoying lack of functionality that I have to work around.
13. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Oct 2007
Posts
2
Rep Power
0
An article in this link can shed some light on the issue

davidflanagan.com/blog/2006_06.html

According to which, C treats -x/y as -(x/y) and also C truncates towards zero, so -5/3 would result in -1 as the quotient and thus the reminder would be -2. Where as in ruby, the quotient q=x/y is such that q*y<=x, and in that case quotient will be equal to -2 as -2*3<-5 and not -1 because then -1*3 would be greater than -5. May be you can say ruby truncates towards - infinity. From this it follows that the -5%3 in Ruby would be 1.
14. Originally Posted by Lux Perpetua
Yes, but in the ANSI standard (which is not obsolete), the behavior is what I claim. Thanks for the correction.
Really? Which ANSI standard are we referring to? C89 (ANSI), C90 (first ISO standard - largely the same as C89 with minor modifications - I would not say this was minor), C99 (second ISO standard, adopted by ASNI in March 2000).

I can't imagine any compiler developer is going to use ANSI X3.159-1989 in preference to either ISO/IEC 9899:1990 or ISO/IEC 9899:1999. So in that sense I would say that it is obsolete because it is superseded. There is an ANSI standard but, for C99 at least, it does not differ from the ISO standard (at least we'd better hope not!).

I have not checked, but I would be surprised if this were not so.

Clifford
15. This has been a very interesting and informative thread. It has pointed out the differences between a remainder operation and a modulus operation.

Good stuff. Both are useful and one needs to know what one requires. Obviously, one cannot depend on naming conventions.

Standards solve some problems regarding portability. They don't solve all. One has to deal, finally, with the implemtation. One-upsmanship doesn't work well, in that regard.
Page 1 of 2 12 Last