Go Down

Topic: modulo with negative int (Read 2513 times) previous topic - next topic

Dimitree

hello
I'm having some difficulties in cycling between a range of value..

Code: [Select]

int c = 0;
int length = 4;
c = -1 % length;
lcd.print(c);


If I use this code I get -1 as result..if I use "unsigned" for c, I get 65535.
I'd like to get 3: (https://www.google.it/#output=search&sclient=psy-ab&q=-1+modulo+4&oq=-1+modulo+4&gs_l=hp.3...1052.1052.0.1909.1.1.0.0.0.0.143.143.0j1.1.0...0.0...1c.1.9.psy-ab.fb5tuCXYaj8&pbx=1&bav=on.2,or.r_qf.&bvm=bv.45512109,d.ZWU&fp=eb10b05648b700fa&biw=1440&bih=755)

If I'm not wrong I used to use % to get always a number in the range of the divisor, both when using negative or positive dividend..
what I'm missing?

marco_c

#1
Apr 22, 2013, 12:12 pm Last Edit: Apr 22, 2013, 12:25 pm by AWOL Reason: 1
http://en.wikipedia.org/wiki/Modulo_operation

Intro paragraph gives you the answer.


Moderator edit: Tags removed
Arduino Libraries https://github.com/MajicDesigns?tab=Repositories
Parola for Arduino https://github.com/MajicDesigns/Parola
Arduino++ blog https://arduinoplusplus.wordpress.com

vtraveller

Sorry it took four years for a reply.  I came across this while looking for the same thing.  Saw the reply and figured it was worthy of something more useful.

Thought about the problem for a few secs and realised its pretty easy to solve.  Just add the length to your value before calculating:

Code: [Select]
int c = 0;
int length = 4;
c = (-1 + length) % length;
lcd.print(c);


In most cases this will suffice as most algorithms just want to loop around arrays and get to the other end of the array when doing some sort of simple traversal.  For me, it was a ring of LEDs I was animating using the FastLED library.

Hope that helps.  If your calculations exceed the length you'll need to add a multiple of length to push the number to be positive before using the modulo operator.

aarg

#3
Jun 04, 2017, 06:53 pm Last Edit: Jun 04, 2017, 07:02 pm by aarg
This one is better, it is not restricted by having to add a fixed offset:
Code: [Select]
void setup() {
  Serial.begin(9600);

  int c;
  const int length = 4;

  for (int i = -10; i <= 10; i++)
  {
    c = (unsigned int)i % length;
    Serial.print(i);
    Serial.print(" is mod ");
    Serial.println(c);
  }
}
void loop() {}
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

Delta_G

But that solution only works for some lengths.  Try it with length = 5.  Look at 0 and -1. 
If at first you don't succeed, up - home - sudo - enter.

aarg

  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

cwalger

Instead of using %, you can write your own function like this:

int mod( int x, int y ){
   return x<0 ? ((x+1)%y)+y-1 : x%y;
}

Then, mod(-1, 4) does return 3 as you'd expect.

Go Up