GameDev.net Posting Guidelines (please read before posting)
For Beginners Forum FAQs (please read before posting)
Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
Posted 28 April 2013 - 06:46 PM
Posted 28 April 2013 - 07:37 PM
POPULAR
Edited by Hodgman, 28 April 2013 - 07:47 PM.
Posted 28 April 2013 - 07:39 PM
Posted 28 April 2013 - 10:04 PM
POPULAR
int n = intrand(); //gives random value between 0 and a bajillion n %= MY_ MAX_RAND; //brings the value into the range 0 to MY_MAX_RAND
//pseudocode int n = 0; loop { n %= 5; print(n++); }0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0.....
Posted 28 April 2013 - 10:56 PM
You can also use it to bring a random int into a range:
int n = intrand(); //gives random value between 0 and a bajillion n %= MY_ MAX_RAND; //brings the value into the range 0 to MY_MAX_RAND
The circular sequence behavior that ultramailman pointed out can be useful in many situations://pseudocode int n = 0; loop { n %= 5; print(n++); }0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0.....
Actually HUGE thank you for this. Just yesterday I was dealing with that and I ended up writing a simple if statement to reset it! I don't think I would have ever thought about using the modulus operator there. Thanks.
Hodgman: That's an interesting example also because I was working out a formula for that the other day. Interesting I ask about this and I immediately get like two examples that I've dealt or thought of.
On what you said about "how do you know when to use addition or division?" That is an interesting question to pose. I would say just because it was drilled into our minds so much in school that you learn to use it while using the modulus isn't really drilled into your mind to use in school. Only reason I can think of I guess...?
Thanks everyone!
Posted 28 April 2013 - 11:40 PM
POPULAR
I would say just because it was drilled into our minds so much in school that you learn to use it while using the modulus isn't really drilled into your mind to use in school. Only reason I can think of I guess...?
In that case, think of it as being basically the same operation as division. With integers, division has two results. You get the quotient with "/" and the remainder with "%".
With floats, division only has one result, you get the "quotient + remainder/divisor" with "/".
You can also use it to bring a random int into a range:
This is a very common usage, but if you require a completely random statistical distribution of random numbers, then this can screw you with a bias.
e.g. say that rand returns numbers from 0-15, but you want numbers 0-12. In this case, the numbers 13/14/15 are wrapped around to 0/1/2, which makes these first three numbers twice as likely to be picked than the rest (3-12) are!
Usually this isn't a problem because rand generates really big numbers, making the bias very small and not noticeable so I would still usually use modulo for this.
It's usually only a problem in very precise scientific simulators, where you'd want to cast the random number to a float and divide by RAND_MAX, to get a normalized range of 0-1, and then scale this value to the desired range.
Edited by Hodgman, 28 April 2013 - 11:44 PM.
Posted 29 April 2013 - 12:13 AM
Some practical everyday uses:
// I want to trigger something every 7 executions:
static int count = 0;
count = ++count % 7;
if( !count ) {do something}
// I want to cycle 0-6 repeatedly.
static int count = 0;
count = ++count % 7;
In the first case the 'if' relies on the fact that the only "true" condition is when something is non-zero. In the second case a value modded by any higher value results in the same value, it goes to zero when modded with itself. Basically a variable in both cases is going to step from 0 to mod value minus one, or 0-6 in this case and keep repeating.
I think I use the first case with the 'if' statement more often but I know I use the second case on occasion also.
Edited by AllEightUp, 29 April 2013 - 01:02 AM.
Posted 29 April 2013 - 12:46 AM
'true' is typically nonzero, isn't it? In c/c++ it would be "if(!count) {stuff}".In the first case the 'if' relies on the fact that the only "true" condition is when something is zero.
#include <iostream> int main() { //print multiples of 5 up to 100 for(int n = 1; n <= 100; ++n) { if(!(n % 5)) {std::cout << n << std::endl;} } }Is zero true in java or something?
Edited by Khatharr, 29 April 2013 - 01:12 AM.
Posted 29 April 2013 - 01:00 AM
'true' is typically nonzero, isn't it? In c/c++ it would be "if(!count) {stuff}".In the first case the 'if' relies on the fact that the only "true" condition is when something is zero.
#include <iostream> int main() { //print multiples of 5 up to 100 for(int n = 1; n <= 100; ++n) { if(!(n % 5)) {std::cout << n << std::endl;} } }Is zero true in java or something?
Blah, sorry.... Typo, "non-zero"..
Posted 29 April 2013 - 01:05 AM
Some practical everyday uses:
// I want to trigger something every 7 executions:
static int count = 0;
count = ++count % 7;
if( count ) {do something}
// I want to cycle 0-6 repeatedly.
static int count = 0;
count = ++count % 7;
In the first case the 'if' relies on the fact that the only "true" condition is when something is zero. In the second case a value modded by any higher value results in the same value, it goes to zero when modded with itself. Basically a variable in both cases is going to step from 0 to mod value minus one, or 0-6 in this case and keep repeating.
I think I use the first case with the 'if' statement more often but I know I use the second case on occasion also.
EDIT: Nvm, no reason for this post I guess. lol. Typo.
Like Khatharr said, in C/C++ it would actually execute every time except when count is 0.
As a quick test:
for(index = 0; index < 10; ++index) { count = ++count % 7; if(count) { std::cout << count << " "; } }
produced output:
1 2 3 4 5 6 1 2 3
Edited by Chad Smith, 29 April 2013 - 01:06 AM.
Posted 29 April 2013 - 01:09 AM
ike Khatharr said, in C/C++ it would actually execute every time except when count is 0.
As a quick test:
for(index = 0; index < 10; ++index) { count = ++count % 7; if(count) { std::cout << count << " "; } }produced output:
1 2 3 4 5 6 1 2 3
Yup, I goofed.. Please don't hang me at the weekly horribly backwards post meeting GameDev holds every week.
Edited by AllEightUp, 29 April 2013 - 01:15 AM.
Posted 29 April 2013 - 01:18 AM
Also, addressing the general topic, if you're wanting both the quotient and the remainder then check to see if there's an intrinsic that can give you both results without having to do the division twice. When the CPU does integer division it actually produces both results, regardless of whether you asked for division or modulus. It's not a huge issue, but division is the heaviest integer math operation for the cpu by a wide margin, so in anything where performance matters it can be good to know if there's an intrinsic. (Don't prematurely optimize, but don't prematurely pessimize either.)
Edit: Apparently there's one in std::div, which is convenient, but poking around for a minute I see that it's common for modern compilers to optimize this problem away in most cases.
I was sort of going to "ask" about that. I knew that division was the "heaviest" integer math for the most part. So I was going to ask if the CPU did something to store both results. though I didn't want to seem like I was trying to "optimize" something or anything like that. I was going to ask out of curiosity. Though felt like it could go beyond this topic and didn't want to get into premature optimization. lol. Just my nerd curiosity. Thanks.
Some practical everyday uses:
// I want to trigger something every 7 executions:
static int count = 0;
count = ++count % 7;
if( count ) {do something}
// I want to cycle 0-6 repeatedly.
static int count = 0;
count = ++count % 7;
In the first case the 'if' relies on the fact that the only "true" condition is when something is zero. In the second case a value modded by any higher value results in the same value, it goes to zero when modded with itself. Basically a variable in both cases is going to step from 0 to mod value minus one, or 0-6 in this case and keep repeating.
I think I use the first case with the 'if' statement more often but I know I use the second case on occasion also.
Like Khatharr said, in C/C++ it would actually execute every time except when count is 0.
As a quick test:
for(index = 0; index < 10; ++index) { count = ++count % 7; if(count) { std::cout << count << " "; } }produced output:
1 2 3 4 5 6 1 2 3Yup, I goofed.. Please don't hang me at the weekly horribly backwards post meeting GameDev holds every week.
I won't...to much. .
I saw your new post after I posted mine, so I edited. Gamedev didn't notify me of a new post with the code editor up. Or i didn't see it. lol.
Posted 29 April 2013 - 01:21 AM
EDIT: Nvm, no reason for this post I guess. lol. Typo.
Like Khatharr said, in C/C++ it would actually execute every time except when count is 0.
Actually, this is a good case of a bad code typo and use case. The fact that I got the example wrong led me to describe the wrong case and I didn't even notice it and I'm a pretty annoying person about details like that..... It leads me to suggest any use of modulus should probably be documented with a comment as to the expectations..
Posted 29 April 2013 - 08:39 AM
You can use mod for "wrapping values":
#include <iostream> #include <string> using namespace std; enum DaysOfWeek { Sunday = 0, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; int main() { int input; cout << "Enter a number for the day of the week you want: "; cin >> input; if(input>6) input = input % 7; if(input<0) input = (input % 7) + 7; string result; switch(input) { case Sunday: result = "Sunday"; break; case Monday: result = "Monday"; break; case Tuesday: result = "Tuesday"; break; case Wednesday: result = "Wednesday"; break; case Thursday: result = "Thursday"; break; case Friday: result = "Friday"; break; case Saturday: result = "Saturday"; break; } cout << result << endl; cin.sync(); cin.ignore(); return 0; }
Posted 29 April 2013 - 08:39 PM
Careful now...
if(input>6) //this condition is (usually) not an effective optimization and is mathematically irrelevant input = input % 7; if(input<0) input = (input % 7) + 7; //this is incorrect in cases where input == n * -7
Try:
input %= 7; if(input<0) input += 7;
Edited by Khatharr, 29 April 2013 - 08:50 PM.
Posted 30 April 2013 - 01:00 AM
Careful now...
if(input>6) //this condition is (usually) not an effective optimization and is mathematically irrelevant input = input % 7; if(input<0) input = (input % 7) + 7; //this is incorrect in cases where input == n * -7
Try:
input %= 7; if(input<0) input += 7;
Thanks about this! Seems I didn't predict the case when (-7*n) % 7 = 0
(In fact I think I did predict it but messed up my conditionals... gotta be careful when coding)
Edited by lightxbulb, 30 April 2013 - 01:35 AM.
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
GameDev.net™, the GameDev.net logo, and GDNet™ are trademarks of GameDev.net, LLC.