• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

 Modulo bug

NightFrost

Member
Modulo of negative numbers is calculated wrong (GMS1 has the same bug).

For example: -90 mod 360 gives me -90 when the correct answer is 270. Somewhat annoying as modulo can be used to create a looping range. I still have to do:
Code:
A = B + C;
if(A < 0) A += 360;
if(A > 359) A -= 360
Instead of:
Code:
A = (B + C) mod 360;
 

Mike

nobody important
GMC Elder
This is correct. open up windows calculator, go into programming mode and do this. you get the same. To me, its a negative number - I want that.

some cases you do, some you don't.
 

csanyk

Member
In terms of plotting a -90 degree angle or a 270 degree angle, they're equivalent, right? If you need to normalize that to a 0-360 number, then 360-90 gets you there.

Of course, if you're doing something other than degrees, that may be a problem...
 

Hyomoto

Member
You are not using it properly. I find it weird that your response to it not working as intended is that it's a bug and not a potential misuse on your part. @Mike is correct, if you plug this into a calculator, you will get the same result. You are asking it what the remainder is when -90 is divided by 360. Since 360 goes into -90 less than once, it returns the original value. -450 mod 360 will return the same value. I'm not sure what you think modulo does, but that's not it.
 
M

McWolke

Guest
I learned that the remainder has to be a positive number, so - 90 would be wrong. It has to be
- 90 = - 1*360 + 270.
So the remainder is 270.
Java does this wrong too.
But i also read that it depends on the conventions the programming language uses how it is implemented.
Anyway, 270 is the real mathematical way.
 

xot

GMLscripter
GMC Elder
The mod operator for GML has been codified for over decade. It's not going to change.
 
C

CedSharp

Guest
you can simply create your own script instead of trying to change something as fundamental as modulo:

modulo
Code:
/// modulo( value, divider )
var result = abs( argument[0] ) mod argument[1];
And then you can just use:
Code:
var res = modulo( -90, 360 ); // returns 90
res = modulo( -361, 360 ); // returns 1
 

NightFrost

Member
Oh, interesting. I've been taught that modulo's result needs to be positive (EDIT - due to needing to satisfy dividend = divisor * quotient + remainder), but apparently there's no rule for this and rather schools of thought. Also, backwards compatibility is a good point against changing anything.
 
Last edited:

NightFrost

Member
And then you can just use:
Code:
var res = modulo( -90, 360 ); // returns 90
res = modulo( -361, 360 ); // returns 1
For the sake of completeness, since the correct answer needs to be 270, the script is little bit more involved. To get a remainder that fits with Euclidean division (must always be positive) the code is:
Code:
if(argument[1] < 0) Q = ceil(argument[0]/argument[1]);
else Q = floor(argument[0]/argument[1]);
return argument[0] - (Q * argument[1]);
 
C

CedSharp

Guest
For the sake of completeness, since the correct answer needs to be 270, the script is little bit more involved. To get a remainder that fits with Euclidean division (must always be positive) the code is:
Code:
if(argument[1] < 0) Q = ceil(argument[0]/argument[1]);
else Q = floor(argument[0]/argument[1]);
return argument[0] - (Q * argument[1]);
True, nice catch there.
I didn't substract the result in case it was negative, that's my bad haha.
 

Hyomoto

Member
If there are other methods, there are other methods and I was a jerk to presume you were using it wrong, rather than just being acquainted with another method. I apologize.
 
Top