Page 1 of 2 12 Last
  • Jump to page:
    #1
  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. #2
  3. Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jun 2005
    Posts
    5,964
    Rep Power
    4852
    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.
    Write no code whose complexity leaves you wondering what the hell you did.
    Politically Incorrect DaWei on Pointers Grumpy on Exceptions
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2007
    Posts
    921
    Rep Power
    537
    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
  6. #4
  7. ASP.Net MVP
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Aug 2003
    Location
    WI
    Posts
    4,378
    Rep Power
    1511
    % returns the remainder. 3 goes into 5 one time with a remainder of 2.
    Primary Forum: .Net Development
    Holy cow, I'm now an ASP.Net MVP!

    [Moving to ASP.Net] | [.Net Dos and Don't for VB6 Programmers]

    http://twitter.com/jcoehoorn
  8. #5
  9. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,117
    Rep Power
    1803
    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 09:46 AM. Reason: typo
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2007
    Posts
    921
    Rep Power
    537
    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.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2004
    Location
    San Francisco Bay
    Posts
    1,939
    Rep Power
    1313
    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 04:07 PM. Reason: Correction
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2007
    Posts
    921
    Rep Power
    537
    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".'

    Comments on this post

    • clifford agrees
    • Lux Perpetua agrees
  16. #9
  17. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,117
    Rep Power
    1803
    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 05:47 AM.
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Oct 2007
    Posts
    921
    Rep Power
    537
    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).

    Comments on this post

    • 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.
  20. #11
  21. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,117
    Rep Power
    1803
    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
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2004
    Location
    San Francisco Bay
    Posts
    1,939
    Rep Power
    1313
    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.
  24. #13
  25. 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.
  26. #14
  27. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,117
    Rep Power
    1803
    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
  28. #15
  29. Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jun 2005
    Posts
    5,964
    Rep Power
    4852
    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.
    Write no code whose complexity leaves you wondering what the hell you did.
    Politically Incorrect DaWei on Pointers Grumpy on Exceptions
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo