views:

1837

answers:

5

I am trying randomly generate a positive or negative number and rather then worry about the bigger range I am hoping to randomly generate either 1 or -1 to just multiply by my other random number.

I know this can be done with a longer rule of generating 0 or 1 and then checking return and using that to either multiply by 1 or -1.

Hoping someone knows of an easier way to just randomly set the sign on a number. Trying to keep my code as clean as possible.

+9  A: 

If I understand the question correctly, you want a pseudorandom sequence of 1 and -1:

int f(void)
{
        return random() & 1 ? 1 : -1;
    //  or...
    //  return 2 * (random() & 1) - 1;
    //  or...
    //  return ((random() & 1) << 1) - 1;
    //  or...
    //  return (random() & 2) - 1; // This one from Chris Lutz
}

Update: Ok, something has been bothering me since I wrote this. One of the frequent weaknesses of common RNGs is that the low order bits can go through short cycles. It's probably best to test a higher-order bit:   random() & 0x80000 ? 1 : -1

DigitalRoss
Chris Lutz
Just a reminder to those folks who aren't familiar with random numbers generated by a deterministic system- they're not really random. You'll probably want to call `srandomdev();` at some convenient "app start-up" point. You only need to call it once. This seeds the random number generator with a source of reasonably random bits so the results from `random()` are "more random". Otherwise, `random()` starts with the exact same seed each time.
johne
Assuming that we're talking about `Xcode.app` / your standard Cocoa application, the most obvious place to put a call to `srandom()` is in the `Xcode.app` provided `main.m` file, in the `main()` function, just before the call to `NSApplicationMain()`.
johne
I like Chris' approach, but agree with Dave DeLong that `arc4random()` is usually preferable since it doesn't require seeding, which means less opportunity for mistakes.
Quinn Taylor
A: 

To generate either 1 or -1 directly, you could do:

int PlusOrMinusOne() {
    return (rand() % 2) * 2 - 1
}

But why are you worried about the broader range?

David Seiler
rand() has some issues. maybe one should consider using something else. http://ianbullard.squarespace.com/journal/2009/4/28/why-you-should-never-use-rand.html
neoneye
A: 

This extra step won't give you any additional "randomness". Just generate your number straight away in the range that you need (e.g. -10..10). Standard rand() will return a value from this range: 0..1 You can multiply it by a constant to increase the span of the range or you can add a constant to push it left/right on the X-Axis. E.g. to generate random values from from (-5..10) range you will have: rand()*15-5

DmitryK
`rand()` returns an `int` (see `man rand`). This means, by definition, it can not return a value `from this range: 0..1`. Furthermore, the use of `rand` is strongly discouraged, and in fact obsoleted by `random()`, because the algorithm used generates very poor quality random numbers. If you want a value between `(double)` `0.0` ... `1.0`, use `drand48()`. Alternatively you can do something like `(double)randomNumber / (double)TYPE_MAX` for `int`ish style random number generators: `double randomNumber = (double)arc4random() / (double)UINT_MAX;`
johne
@johne - I Think Dmitry was confusing Java with ObjectiveC...
Jason Coco
Sorry for the confusion. I didn't mean any language specifically, but rather a generic function that returns a random (float) value from 0..1 range. My main focus was to explain how to transform it to any other range (i.e. that you don't need that -1 or 1 random value generated)
DmitryK
A: 

rand will give you a number from 0 to RAND_MAX which will cover every bit in an int except for the sign. By shifting that result left 1 bit you turn the signed MSB into the sign, but have zeroed-out the 0th bit, which you can repopulate with a random bit from another call to rand. The code will look something like:

int my_rand()
{
    return (rand() << 1) + (rand() & 1);
}
fbrereto
-1 for overcomplicating a simple Objective-C problem with unnecessarily complex C++. Usually I wouldn't care enough about such issues to downvote, but the C standard library has perfectly good random number functions that don't require pulling in C++, which can have some rather nasty side effects and complicate compilation, runtime, etc.
Quinn Taylor
I pulled out the std:: namespace, so it's now valid C. `std::rand` is the same `rand` C uses, just protected behind the `std` namespace to avoid collisions.
fbrereto
+4  A: 

I like to use arc4random() because it doesn't require you to seed the random number generator. It also conveniently returns a uint_32_t, so you don't have to worry about the result being between 0 and 1, etc. It'll just give you a random integer.

int myRandom() {
  return (arc4random() % 2 ? 1 : -1);
}
Dave DeLong
+1 for simple and straightforward.
Quinn Taylor