The behavior of the operator %

W

Walter Roberson

: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);
 
A

Andrey Tarasevich

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!
...

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).
 
O

osmium

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!

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.
 
A

Andrey Tarasevich

Andrey said:
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

A typo. Should be:

[...] you'll see -1/10 == 0 and -1%10 == -1. [...]
 
M

Mark McIntyre

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!

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.
 
C

Christian Bau

A

Andrey Tarasevich

P.J. Plauger said:
...

How 'bout div and ldiv?
...

According to what I see in C89/90, these functions are required to round
the quotient towards zero.
 
R

Richard Bos

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);

Or replace the whole lot by

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

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

Richard
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top