The behavior of the operator %

Discussion in 'C Programming' started by PengYu.UT, Mar 18, 2005.

  1. PengYu.UT

    PengYu.UT Guest

    Hi All,

    I know the result of the operator % is the remainder. But I don't find
    the detailed descriptions, for example from K&R's book
    http://freebooks.by.ru/view/CProgrammingLanguage/chapter2.html#s2.5

    I tried -1 % 10. It gave me -1. How can I make the remainder has the
    same sign as the divider? How to get -1 % 10 = 9? Thanks!

    Best wishes,
    Peng
     
    PengYu.UT, Mar 18, 2005
    #1
    1. Advertisements

  2. :I know the result of the operator % is the remainder.

    :I tried -1 % 10. It gave me -1. How can I make the remainder has the
    :same sign as the divider? How to get -1 % 10 = 9? Thanks!

    In C89, the sign of the result is implimentation dependant.
    In C99, they mandated one of the two reasonable behaviours -- and
    the behaviour they mandated was the one that will give you negative
    results.

    There is no standard C pragma or control that can be used to
    force one behaviour over the other [though an implimentation might
    choose to provide a mechanism], so you will pretty much just have
    to test the result -- perhaps with something like

    R = M % N;
    R += N * ((R < 0 && N > 0) || (R > 0 && N < 0));

    Or to be more obtruse,

    R += N * (copysign(1,R) * copysign(1,N) < 0);
     
    Walter Roberson, Mar 18, 2005
    #2
    1. Advertisements

  3. It makes sens to have the result of % operator to be in agreement with
    the result of / operator (integral division) in a sense that from

    q = a / b
    r = a % b

    should follow that

    a = b * q + r

    Now, what do you think is the result of -1/10? In C89/90, both 0 and -1
    are acceptable results. The standard leaves this decision to the
    implementation (i.e. it is implementation-defined). If some
    implementation decides to evaluate -1/10 as 0, then normally it will
    evaluate -1%10 as -1. If some other implementation evaluates -1/10 as
    -1, then normally it will evaluate -1%10 as 9.

    The C89/90 standard _recommends_ that implementation use the former
    variant (Fortran-style division, rounding to 0), meaning that most of
    the time you'll see -1/10 == 0 and -1/10 == -1. That's probably what
    happens in your case. C99 standard upgraded this recommendation to the
    level of mandatory requirement.

    If you want the other behavior, you have to implement it manually. If
    you are using a C89/90 compiler, you can also try to look for a compiler
    option that control this behavior on program-wide scale (if that's what
    you need).
     
    Andrey Tarasevich, Mar 18, 2005
    #3
  4. PengYu.UT

    osmium Guest

    The phrase "machine dependant" means the sign depends on the machine on
    which the program is being run. The language does not specify a result.
     
    osmium, Mar 18, 2005
    #4
  5. A typo. Should be:

    [...] you'll see -1/10 == 0 and -1%10 == -1. [...]
     
    Andrey Tarasevich, Mar 18, 2005
    #5
  6. AFAIR in C89, this is platform specific and you need to work around it.

    Bear in mind that both -1 and 9 are valid answers as long as both operands are
    integers, since the result must satisfy (a/b)*b+a%b =a, and its
    implementation-defined whether -1/10 is -1 or 0 (round down or up). I seem to
    recall that C99 changed this to always round towards zero, but I can't find the
    reference.
     
    Mark McIntyre, Mar 18, 2005
    #6
  7. If the result has the wrong sign, then just add the divisor and the sign
    will be correct.
     
    Christian Bau, Mar 19, 2005
    #7
  8. According to what I see in C89/90, these functions are required to round
    the quotient towards zero.
     
    Andrey Tarasevich, Mar 19, 2005
    #8
  9. PengYu.UT

    Richard Bos Guest

    Or replace the whole lot by

    R = ((M%N)+N) % N);

    if you know that it'll always be used with positive N.

    Richard
     
    Richard Bos, Mar 21, 2005
    #9
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.