Re: Warnings when using % operator
From: Derrick Coetzee (dcnews_at_moonflare.com)
Date: 09/16/04
- Next message: Derrick Coetzee: "Re: Warnings when using % operator"
- Previous message: Charlie Gordon: "Re: Two Questions about "strlen", "strcat" and "strcpy""
- In reply to: Tim Rentsch: "Re: Warnings when using % operator"
- Next in thread: Derrick Coetzee: "Re: Warnings when using % operator"
- Reply: Derrick Coetzee: "Re: Warnings when using % operator"
- Reply: Tim Rentsch: "Re: Warnings when using % operator"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Thu, 16 Sep 2004 03:20:36 -0400
Tim Rentsch wrote:
> This brings up an interesting challenge - how can IMOD be written
> so that (1) it handles any combination of signed and unsigned
> operands, and (2) doesn't generate compiler warnings like the
> one mentioned in the earlier posting caused by comparing an
> unsigned value to be less than zero? The desired semantics
> are to return the smallest non-negative 'r' such that
>
> i == m * j + r
>
> with 'm' and 'r' being integers. For simplicity feel free to
> assume that j != 0 and the value of 'r' can be represented as
> a value of the type of 'i % j'.
Neither assumption is needed: 0 <= r < |j|, and % takes the type of j.
The answer seems simple to me - transform before, not afterwards:
#define IMOD(i,j) ((i) <= 0 \
? ((j) <= 0 ? -j - ((-i) % (-j)) : j - ((-i) % (j))) \
: ((j) <= 0 ? (i) % (-j) : (i) % (j)))
Then, if i == m*j + r, then all the following also hold:
i == (-m)*(-j) + r // i pos, j neg
-i == (m-1)*(-j) - j - r // i neg, j neg, -j > r
-i == (m-1)*j + j - r // i neg, j pos, j > r
The remainder parts are all the smallest positive possible, since
they're all positive and all < j.
I'm avoiding the compiler warning for unsigned i and j by using "i <= 0"
and "j <= 0" rather than "i < 0" and "j < 0" (it doesn't matter which
branch we use for zero). Here's a complete sample that runs and produces
correct answers with no warnings with gcc -Wall:
#include <stdio.h>
#define IMOD(i,j) ((i) <= 0 \
? ((j) <= 0 ? -j - ((-i) % (-j)) : j - ((-i) % (j))) \
: ((j) <= 0 ? (i) % (-j) : (i) % (j)))
int main() {
printf("%d %d %d %d %d\n", IMOD(5u,3u), IMOD(5,3), IMOD(-5,3),
IMOD(5,-3), IMOD(-5,-3));
return 0;
}
> By the way, am I right in thinking that in a standard-compliant
> compilation the expression '-1 % 2 > 0' will always be zero (that
> is, false)?
Nope. "If both operands are nonnegative then the remainder is
nonnegative; if not, the sign of the remainder is
implementation-defined." - ISO C++ Standard, 5.6
However, there is an implicit constraint in this promise:
"(a/b)*b + a%b is equal to a"
But we know how multiplication and integer division behave; if you work
it out, (a/b)*b must have the sign of a, and be no further from zero
than a. Consequently, if a is negative, a%b must be nonpositive, in
order to "get back" to a. Similarly, if a is positive, a%b must be
nonnegative, regardless of the sign of b, to satisfy this constraint. I
think pretty much all implementations overlooked this, though.
-- Derrick Coetzee I grant this newsgroup posting into the public domain. I disclaim all express or implied warranty and all liability. I am not a professional.
- Next message: Derrick Coetzee: "Re: Warnings when using % operator"
- Previous message: Charlie Gordon: "Re: Two Questions about "strlen", "strcat" and "strcpy""
- In reply to: Tim Rentsch: "Re: Warnings when using % operator"
- Next in thread: Derrick Coetzee: "Re: Warnings when using % operator"
- Reply: Derrick Coetzee: "Re: Warnings when using % operator"
- Reply: Tim Rentsch: "Re: Warnings when using % operator"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|