Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Modulus and negative operands

Reply
Thread Tools

Modulus and negative operands

 
 
August Karlstrom
Guest
Posts: n/a
 
      01-12-2006
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

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
 
Reply With Quote
 
 
 
 
Michael Mair
Guest
Posts: n/a
 
      01-12-2006
August Karlstrom wrote:
> 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
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
 
 
 
August Karlstrom
Guest
Posts: n/a
 
      01-12-2006
Michael Mair wrote:
> % 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

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
 
Reply With Quote
 
Michael Mair
Guest
Posts: n/a
 
      01-12-2006
August Karlstrom wrote:
> Michael Mair wrote:
>
>> % 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-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      01-12-2006


August Karlstrom wrote On 01/12/06 14:01,:
> Michael Mair wrote:
>
>>% 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;

--




 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Modulus of a negative number Jim Hunter C Programming 3 05-03-2010 11:04 PM
Conversion rules between unsigned operands and signed operand somenath C Programming 11 07-30-2007 10:37 AM
operators requiring lvalue/rvalue operands and resulting in rvalue/lvalue Kavya C Programming 9 10-28-2006 01:45 AM
Problem with SLL: "sll can not have such operands in this context" and bit-testing Frank Buss VHDL 5 07-01-2006 04:26 PM
Negative setup and Negative hold prem_eda VHDL 5 10-11-2004 12:14 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57