views:

68

answers:

3

I have a very basic random number function which generates a random number from a range;

ie:

// The random is seeded earlier on in the applicationDidFinishLaunching() function
-(NSUInteger)makeRandomNumber:(NSUInteger)minNumber to:(NSUInteger)maxNumber
{
 //NSUInteger i = (NSUInteger)( (random() / (double)RAND_MAX) * y);

 NSUInteger i = (arc4random() % (maxNumber - minNumber)) + minNumber; 
 return i;
}

I want to add an optional modulus operation to this function, so that you only return numbers that are modulus of something.

I'm wanting to do this to generate Wages for random people, I find that wages that round with a 5 or 0 much more readable.

I'm not sure how to make an optional parameter or force the randomisation to continue looping until it has found the optional modulus value.

Another issue is that sometimes the loop can continue forever if there is no modulus to find.

ie;

Randomise between 0 and 100 and return a value that is modulus of 5.

EDIT: This should work with any range, regardless of what min or max are. The above numbers are just examples.

+2  A: 

ITYM multiple of 5. For your example you would just generate a random value between 0 and 20 then multiply this by 5.

Paul R
Agreed. You're 43 secs faster than me.
adib
-1. This doesn't give equal probability to all possible outputs either. you'll have a 0.5% chance of generating a 0, 1% chance of generating numbers 1-19, and a 0.5% chance of generating a 20. Unless you provide some code to modify the OP's random number generator.
Stephen Furlani
@Stephen Furlani: I didn't say that the OP should use his existing RNG - I just said "generate a random value between 0 and 20 then multiply this by 5".
Paul R
I was using 5 as an example, it could be 25, 50, 10, I guess the multiplication could be used just as well.
zardon
Further, how do you make an optional parameter?
zardon
This doesn't make sense. If I randomly generate 0-20, then multiply the result by 5 I can possibly get a number higher than 20.This is different to what I'm after. If I random between 0-20, and I want a modulus of 5, the only answers I should get back should be 5,10,15,or 20.If I've mis-understood/mis-interrepted what you meant, please forgive me.
zardon
@worchyld: the example you give in your question is "Randomise between 0 and 100 and return a value that is modulus of 5" -- to do this you take a random number from 0 to 20 and multiply by 5. I hope you can see the general principle from this - obviously it works for any range and any multiple.
Paul R
I think I get it, let's assume I want to randomise between 0 and 10,000 and only return those numbers that are modulus' of 500.If I read you correct, you would need to divide 10,000 by 500 (=20), then randomise between 0 and 20; then multiply the sum by 10,000.Again, with another example.I want to rand between 25k and 100k and only return results that are modulus of 25k. Thus, 100k/25k = 4. Rand(1,4) = 3. 3 * 25k = 75kI think, if my maths is right, this looks like the best answer. Thanks Paul R
zardon
A: 

I think a loop will work well enough:

 NSUInteger i = 0;
 do {
   NSUInteger i = (arc4random() % (maxNumber - minNumber)) + minNumber; 
 } while(i % 5 != 0);
vodkhang
This is rather inefficient and unnecessarily complicated. Also I think your terminating condition needs to be `while ((i % 5) != 0)` ?
Paul R
yeah, sure, it is my fault. It is 20% chance and if you don't call that really often, efficiency will not be big problem
vodkhang
This loop works great, but I notice Paul R says it is inefficient. I'm quite happy to use a more efficient resolution. Thanks.
zardon
yeah, sure, you should go for Paul R answer. It is a better one
vodkhang
A: 

Integer division will make sure your number is a multiple of roundNumber only as it truncates the decimal in the divide, and then restores the original rounded number in the multiply.

// The random is seeded earlier on in the applicationDidFinishLaunching() function
-(NSUInteger)makeRandomNumber:(NSUInteger)minNumber to:(NSUInteger)maxNumber round:(NSUInteger) roundNumber
{   
 NSUInteger i = (arc4random() % (maxNumber - minNumber)) + minNumber; 
 return (i / roundNumber) * roundNumber;
}
Stephen Furlani
This doesn't give equal probability to all possible outputs - e.g. for the above example (0..100), 100 will occur less frequently than the other possible values.
Paul R
@Paul, well, yes. Since you're rounding/truncating the values they can't have even distribution. For example, even if you followed a decent rounding rule (.5) 0 would only be called if the value was 0-> .499 whereas 1 would be called if the value was 0.5->1.4999. I'll point out that your answer doesn't address this issue of equal probability either.equal probability was also not a requirement by the OP. Readability , and an optional rounding parameter, was.
Stephen Furlani