Modulus and negative operands

A

August Karlstrom

Hi,

How come the modulus operator doesn't always yield non-negative values?
I expect e.g. (-1) % 3 to be 2 but I get -1. If I want to decrement a
cyclic variable n by k I have to write something like

n = ((n - k) % length + length) % length

where as in e.g. Pascal i can simply write

n := (n - k) MOD length

to get the desired result.


August
 
M

Michael Mair

August said:
Hi,

How come the modulus operator doesn't always yield non-negative values?
I expect e.g. (-1) % 3 to be 2 but I get -1. If I want to decrement a
cyclic variable n by k I have to write something like

n = ((n - k) % length + length) % length

where as in e.g. Pascal i can simply write

n := (n - k) MOD length

to get the desired result.

% is defined in terms of / (see below).
If / rounds down, then % yields positive values.
If / rounds to zero, you get the observed behaviour.
C89 allows both, C99 only round-to-zero.

From the last public draft of C89:
,---
3.3.5 Multiplicative operators

Syntax

multiplicative-expression:
cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression

Constraints

Each of the operands shall have arithmetic type. The operands of
the % operator shall have integral type.

Semantics

The usual arithmetic conversions are performed on the operands.

The result of the binary * operator is the product of the operands.

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.

When integers are divided and the division is inexact, if both
operands are positive the result of the / operator is the largest
integer less than the algebraic quotient and the result of the %
operator is positive. If either operand is negative, whether the
result of the / operator is the largest integer less than the
algebraic quotient or the smallest integer greater than the algebraic
quotient is implementation-defined, as is the sign of the result of
the % operator. If the quotient a/b is representable, the expression
(a/b)*b + a%b shall equal a .
`---

Cheers
Michael
 
A

August Karlstrom

Michael said:
% is defined in terms of / (see below).
If / rounds down, then % yields positive values.
If / rounds to zero, you get the observed behaviour.
[snip]

OK, but what's the benefit of this behavior?


August
 
M

Michael Mair

August said:
Michael said:
% is defined in terms of / (see below).
If / rounds down, then % yields positive values.
If / rounds to zero, you get the observed behaviour.

[snip]

OK, but what's the benefit of this behavior?

- It is well-defined.
- Probably historical reasons.

If you are asking for more of a rationale,
http://www.lysator.liu.se/c/rat/c3.html#3-3-5 comes to mind.
Probably this is not enough, either. Maybe someone else
can contribute more.


Cheers
Michael
 
E

Eric Sosman

August Karlstrom wrote On 01/12/06 14:01,:
Michael said:
% is defined in terms of / (see below).
If / rounds down, then % yields positive values.
If / rounds to zero, you get the observed behaviour.

[snip]

OK, but what's the benefit of this behavior?

The benefit of "truncate toward zero" on division are
mostly conventional: That's the way practically all known
hardware does division, and that's also the way Fortran
defines it. According to the C99 Rationale, compatibility
with Fortran was the main reason for requiring "truncate
toward zero."

Quotient and remainder are governed by the identity

(a / b) * b + (a % b) == a

(unless the division itself is undefined). Whichever
way the quotient is chosen on an inexact division, the
modulus must "balance" the truncation error. If division
truncates toward zero, the truncated negative quotient
will be larger than the true mathematical quotient, so
the "correction" must be negative.
If I want to decrement a
cyclic variable n by k I have to write something like

n = ((n - k) % length + length) % length

If k <= length, this can be simplified to

n = (n - k + length) % length

or to

if ((n -= k) < 0)
n += length;
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top