[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

mod operator for signed integers

dr.oktopus

4/9/2011 2:53:00 PM

Ok, today I seems to be a little dumb.
What I have to do is to make mod operator (m % n) work even
if m is a negative number.

This is what I mean:

given n = 5

7 became 2
6 .. 1
5 .. 0
4 .. 4
3 .. 3
2 .. 2
1 .. 1
0 .. 0
-1 .. 4
-2 .. 3
-3 .. 2
-4 .. 1
-5 .. 0
-6 .. 4
-7 .. 3

I think that, for a operation like m % n, it could be:

unsigned my_mod (int m, unsigned n)
{
unsigned um;

if (m < 0) {
um = -m;
return n - um % n;
}
return m % n;
}

but, if m is INT_MIN, for example, its two complement (um)
is 0, right? So, my_mod returns n (that is wrong).

What's the right (and smart) way?
17 Answers

Geoff

4/9/2011 4:52:00 PM

0

On Sat, 9 Apr 2011 07:53:05 -0700 (PDT), "dr.oktopus"
<blindwilly@freeonline.zzn.com> wrote:

>Ok, today I seems to be a little dumb.
>What I have to do is to make mod operator (m % n) work even
>if m is a negative number.
>
>This is what I mean:
>
>given n = 5
>
> 7 became 2
> 6 .. 1
> 5 .. 0
> 4 .. 4
> 3 .. 3
> 2 .. 2
> 1 .. 1
> 0 .. 0
>-1 .. 4
>-2 .. 3
>-3 .. 2
>-4 .. 1
>-5 .. 0
>-6 .. 4
>-7 .. 3
>
>I think that, for a operation like m % n, it could be:
>
>unsigned my_mod (int m, unsigned n)
>{
> unsigned um;
>
> if (m < 0) {
> um = -m;
> return n - um % n;
> }
> return m % n;
>}
>
>but, if m is INT_MIN, for example, its two complement (um)
>is 0, right? So, my_mod returns n (that is wrong).
>
>What's the right (and smart) way?

r = m < 0 ? -m % n : m % n;
return r;

Geoff

4/9/2011 5:38:00 PM

0

On Sat, 09 Apr 2011 09:51:59 -0700, Geoff <geoff@invalid.invalid>
wrote:

>On Sat, 9 Apr 2011 07:53:05 -0700 (PDT), "dr.oktopus"
><blindwilly@freeonline.zzn.com> wrote:
>
>>Ok, today I seems to be a little dumb.
>>What I have to do is to make mod operator (m % n) work even
>>if m is a negative number.
>>
>>This is what I mean:
>>
>>given n = 5
>>
>> 7 became 2
>> 6 .. 1
>> 5 .. 0
>> 4 .. 4
>> 3 .. 3
>> 2 .. 2
>> 1 .. 1
>> 0 .. 0
>>-1 .. 4
>>-2 .. 3
>>-3 .. 2
>>-4 .. 1
>>-5 .. 0
>>-6 .. 4
>>-7 .. 3
>>
>>I think that, for a operation like m % n, it could be:
>>
>>unsigned my_mod (int m, unsigned n)
>>{
>> unsigned um;
>>
>> if (m < 0) {
>> um = -m;
>> return n - um % n;
>> }
>> return m % n;
>>}
>>
>>but, if m is INT_MIN, for example, its two complement (um)
>>is 0, right? So, my_mod returns n (that is wrong).
>>
>>What's the right (and smart) way?
>
> r = m < 0 ? -m % n : m % n;
> return r;

Correction:

r = m < 0 ? 0-m % n : m % n;
return r;

io_x

4/9/2011 5:45:00 PM

0


"Geoff" <geoff@invalid.invalid> ha scritto nel messaggio
news:vk31q617k5188j3qfsalvqj4hjnl05n57h@4ax.com...
> On Sat, 9 Apr 2011 07:53:05 -0700 (PDT), "dr.oktopus"
> <blindwilly@freeonline.zzn.com> wrote:
>
>>Ok, today I seems to be a little dumb.
>>What I have to do is to make mod operator (m % n) work even
>>if m is a negative number.
>>
>>This is what I mean:
>>
>>given n = 5
>>
>> 7 became 2
>> 6 .. 1
>> 5 .. 0
>> 4 .. 4
>> 3 .. 3
>> 2 .. 2
>> 1 .. 1
>> 0 .. 0
>>-1 .. 4
>>-2 .. 3
>>-3 .. 2
>>-4 .. 1
>>-5 .. 0
>>-6 .. 4
>>-7 .. 3
>>
>>I think that, for a operation like m % n, it could be:
>>
>>unsigned my_mod (int m, unsigned n)
>>{
>> unsigned um;
>>
>> if (m < 0) {
>> um = -m;
>> return n - um % n;

here if for example n=5 and um=10 [m==-10]
n - um % n== 5 - (10%5) == 5 but the result has to be 0..4
so it should be one test
if(result==5) result=0;

>> }
>> return m % n;
>>}
>>
>>but, if m is INT_MIN, for example, its two complement (um)
>>is 0, right? So, my_mod returns n (that is wrong).
>>
>>What's the right (and smart) way?
>
> r = m < 0 ? -m % n : m % n;

i think this

r = (m<0 ? (n-(-m%n))%n : m%n)

or better

unsigned myMod(int m, unsigned n)
{unsigned mm;

// prevent seg fault on error but wrong result
if(n==0) return -1;
if(m>=0) {mm=m; return mm%n;}
mm=-m; mm%=n;
if(mm==n) mm=0;
return mm;
}

but this is untested and i can make wrong on that
Buona giornata.

> return r;




Willem

4/9/2011 6:02:00 PM

0

dr.oktopus wrote:
) Ok, today I seems to be a little dumb.
) What I have to do is to make mod operator (m % n) work even
) if m is a negative number.

% is the remainder operator, not the mod operator.
However, observe that the result is still equivalent within
the given modulus.

Therefore, this should work:

r = m % n;
if (r < 0) r += n;

Or if you want a single expression:

r = ((m % n) + n) % n;


HTH.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

io_x

4/9/2011 6:15:00 PM

0


"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4da09adc$0$18241$4fafbaef@reader2.news.tin.it...
>
> "Geoff" <geoff@invalid.invalid> ha scritto nel messaggio
> news:vk31q617k5188j3qfsalvqj4hjnl05n57h@4ax.com...
>> On Sat, 9 Apr 2011 07:53:05 -0700 (PDT), "dr.oktopus"
>> <blindwilly@freeonline.zzn.com> wrote:
>>
>>>Ok, today I seems to be a little dumb.
>>>What I have to do is to make mod operator (m % n) work even
>>>if m is a negative number.
>>>
>>>This is what I mean:
>>>
>>>given n = 5
>>>
>>> 7 became 2
>>> 6 .. 1
>>> 5 .. 0
>>> 4 .. 4
>>> 3 .. 3
>>> 2 .. 2
>>> 1 .. 1
>>> 0 .. 0
>>>-1 .. 4
>>>-2 .. 3
>>>-3 .. 2
>>>-4 .. 1
>>>-5 .. 0
>>>-6 .. 4
>>>-7 .. 3
>>>

i get only the 3,2,1,0,1,2,3

for me you search somethin like the routine
unsigned myModAlternative(int m, unsigned n)
don't know if it is right [but it is very like as that]

#include <stdio.h>

unsigned myMod(int m, unsigned n)
{unsigned mm;

// prevent seg fault on error but wrong result
if(n==0) return -1;
if(m>=0) {mm=m; return mm%n;}
mm=-m; mm%=n;
if(mm==n) mm=0;
return mm;
}

unsigned myModAlternative(int m, unsigned n)
{unsigned mm;

// prevent seg fault on error but wrong result
if(n==0) return -1;
if(m>=0) {mm=m; return mm%n;}
mm=-m; mm%=n;
if(mm==0) mm=n;
return n-mm;
}


int main(void)
{int i, m, n;
n=5;

for(i=7; i> -7 ; --i)
printf("%2d%%%d = %u\n", i, n, myMod(i, n));

printf("Alternative\n");
for(i=7; i> -7 ; --i)
printf("%2d%%%d = %u\n", i, n, myModAlternative(i, n));

return 0;
}

7%5 = 2
6%5 = 1
5%5 = 0
4%5 = 4
3%5 = 3
2%5 = 2
1%5 = 1
0%5 = 0
-1%5 = 1
-2%5 = 2
-3%5 = 3
-4%5 = 4
-5%5 = 0
-6%5 = 1
Alternative
7%5 = 2
6%5 = 1
5%5 = 0
4%5 = 4
3%5 = 3
2%5 = 2
1%5 = 1
0%5 = 0
-1%5 = 4
-2%5 = 3
-3%5 = 2
-4%5 = 1
-5%5 = 0
-6%5 = 4




Eric Sosman

4/9/2011 6:29:00 PM

0

On 4/9/2011 10:53 AM, dr.oktopus wrote:
> Ok, today I seems to be a little dumb.
> What I have to do is to make mod operator (m % n) work even
> if m is a negative number.
>
> This is what I mean:
>
> given n = 5
>
> 7 became 2
> 6 .. 1
> 5 .. 0
> 4 .. 4
> 3 .. 3
> 2 .. 2
> 1 .. 1
> 0 .. 0
> -1 .. 4
> -2 .. 3
> -3 .. 2
> -4 .. 1
> -5 .. 0
> -6 .. 4
> -7 .. 3
>
> I think that, for a operation like m % n, it could be:
>
> unsigned my_mod (int m, unsigned n)
> {
> unsigned um;
>
> if (m< 0) {
> um = -m;
> return n - um % n;
> }
> return m % n;
> }
>
> but, if m is INT_MIN, for example, its two complement (um)
> is 0, right? So, my_mod returns n (that is wrong).

If `m' is INT_MIN, `-m' is either INT_MAX (on some very rare
machines) or undefined (on most). The commonest "undefined" outcome
is -INT_MIN -> INT_MIN, still negative.

> What's the right (and smart) way?

I don't know if this is "the" right or smart way, but:

unsigned my_mod(int m, unsigned n) {
if (m < 0) {
unsigned um;
m += (int)n; /* now m > INT_MIN */
um = -m;
return n - um % n;
}
return m % n;
}

This will not work if `n' is zero (obviously) or >INT_MAX.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Eric Sosman

4/9/2011 7:35:00 PM

0

On 4/9/2011 1:37 PM, Geoff wrote:
> On Sat, 09 Apr 2011 09:51:59 -0700, Geoff<geoff@invalid.invalid>
> wrote:
>
>> On Sat, 9 Apr 2011 07:53:05 -0700 (PDT), "dr.oktopus"
>> <blindwilly@freeonline.zzn.com> wrote:
>>
>>> Ok, today I seems to be a little dumb.
>>> What I have to do is to make mod operator (m % n) work even
>>> if m is a negative number.
>>>
>>> This is what I mean:
>>>
>>> given n = 5
>>>
>>> 7 became 2
>>> 6 .. 1
>>> 5 .. 0
>>> 4 .. 4
>>> 3 .. 3
>>> 2 .. 2
>>> 1 .. 1
>>> 0 .. 0
>>> -1 .. 4
>>> -2 .. 3
>>> -3 .. 2
>>> -4 .. 1
>>> -5 .. 0
>>> -6 .. 4
>>> -7 .. 3
>>>
>>> I think that, for a operation like m % n, it could be:
>>>
>>> unsigned my_mod (int m, unsigned n)
>>> {
>>> unsigned um;
>>>
>>> if (m< 0) {
>>> um = -m;
>>> return n - um % n;
>>> }
>>> return m % n;
>>> }
>>>
>>> but, if m is INT_MIN, for example, its two complement (um)
>>> is 0, right? So, my_mod returns n (that is wrong).
>>>
>>> What's the right (and smart) way?
>>
>> r = m< 0 ? -m % n : m % n;
>> return r;
>
> Correction:
>
> r = m< 0 ? 0-m % n : m % n;
> return r;

Still wrong when m==INT_MIN, the case the O.P. asked about.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Eric Sosman

4/9/2011 7:40:00 PM

0

On 4/9/2011 2:02 PM, Willem wrote:
> dr.oktopus wrote:
> ) Ok, today I seems to be a little dumb.
> ) What I have to do is to make mod operator (m % n) work even
> ) if m is a negative number.
>
> % is the remainder operator, not the mod operator.
> However, observe that the result is still equivalent within
> the given modulus.
>
> Therefore, this should work:
>
> r = m % n;
> if (r< 0) r += n;

Observe that `n' is `unsigned', so `m % n' is equivalent
to `(unsigned)m + n', which for negative `m' is equivalent to
(in mathematical notation now) `(UINT_MAX + 1 + m) % n', which
means the expression is wrong unless `n' divides UINT_MAX+1,
that is, unless `n' is an integral power of 2.

For example, with `m == -1' `n == 5u', `UINT_MAX=65535',
this formula produces the answer 0, while the O.P. wanted 4.

> Or if you want a single expression:
>
> r = ((m % n) + n) % n;

Same problem.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Eric Sosman

4/9/2011 7:44:00 PM

0

On 4/9/2011 2:14 PM, io_x wrote:
> [...]
> unsigned myModAlternative(int m, unsigned n)
> {unsigned mm;
>
> // prevent seg fault on error but wrong result
> if(n==0) return -1;
> if(m>=0) {mm=m; return mm%n;}
> mm=-m;[...]

The O.P. specifically asked about the case m==INT_MIN, and
this "solution" has exactly the same issues as the original,
with the question (and problems) unaddressed.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Eric Sosman

4/9/2011 7:50:00 PM

0

On 4/9/2011 3:40 PM, Eric Sosman wrote:
> On 4/9/2011 2:02 PM, Willem wrote:
>> dr.oktopus wrote:
>> ) Ok, today I seems to be a little dumb.
>> ) What I have to do is to make mod operator (m % n) work even
>> ) if m is a negative number.
>>
>> % is the remainder operator, not the mod operator.
>> However, observe that the result is still equivalent within
>> the given modulus.
>>
>> Therefore, this should work:
>>
>> r = m % n;
>> if (r< 0) r += n;
>
> Observe that `n' is `unsigned', so `m % n' is equivalent
> to `(unsigned)m + n', [...]

Oops. s/+/%/

--
Eric Sosman
esosman@ieee-dot-org.invalid