views:

505

answers:

11

Hello everyone!

I need to generate two numbers that are NOT equal in PHP.

I know that I use $random1 = (rand()%9); to generate random a number between 0-9. I need to add something to this I guess.

Thanks!

+1  A: 

If you simply want unique numbers, just start at zero and add +1 for every new number.

If you need random unique numbers, just save your previous numbers in a list and when you need a new one, just generate random numbers until you found one, which is not in that list.

If you need unique identifiers, you can use the built-in function uniqid.

DR
+15  A: 
$rnd1 = rand(0,9);
do {
  $rnd2 = rand(0,9);
} while ($rnd1 == $rnd2);
Zed
Theoretically, this could loop forever if the numbers were truly random. Unlikely in most computer applications but the running time *is* nondeterministic, which may not be desirable.
paxdiablo
Fortunately most computer's use practical and not theoretical random generators :). In return the two randoms are independent of each other (except for the original constraint).
Zed
Thanks, works like a charm!
Fred Bergman
@Fred, if you want to be sure this code won't run for years as suggested, you can set up a counter to count retries, and after a threshold simply return ($rnd1+1)%10, or whatever.
Zed
Theoretically, a meteorite could hit the server room any time and destroy everything within. In practice, it won't. Don't worry about low probabilities.
DrJokepu
Actually, @DrJokepu, we do plan for that eventuality (not necessarily a meteorite but definitely a server location being destroyed). We have a backup site 50-odd kilometers away. I remember one paranoid asking what we'd do if a disaster took out both locations. My answer was that, for any disaster that big, we'd have a lot more problems on our hands than some lost data.
paxdiablo
while system impact will indeed be minimal, performance wise this isn't the best method, on the other hand, memory wise mine isn't either. I guess this can be solved in multple ways and which is best is determined by the situation you need to use it in.
ChrisR
@Chris, but what guarantees can you give on the distribution or variance on the two random variables generated by your method?
Zed
@Zed regarding ($rnd1+1)%10: because you do not have an even distribution. Randomly generate a number 0 - 9 which means each number has a 1:10 chance. Next generate a 2nd number. If the number is the same as the first then use the next number. Let's say the 1st number is 6. If the 2nd number is 6 or 7 then the 2nd number is really 7. That's a 1:5 chance. Very different odds than the solution in your original post which is in fact the best answer. Could it run forever? Yes. Could a plane crash into your house while it's running? Yes, and at a certain point you're playing with the same odds.
Dinah
+6  A: 
$random1 = (rand() % 10)
$random2 = $random1 + (rand()%9)+1

In this way they are never equal(as at least 1 will be added to $random1 )

if both number have to be from 0-9, you just have to do it with a last mod-operation:

$random1 = (rand() % 10)
$random2 = ($random1 + (rand()%9)+1 ) %10
Peter Parker
I like that one. Nice use of modulus.
Kobi
This mucks up the standard distribution - lower numbers become _slightly_ more probable than higher ones, though in this case it may not be noticeable.
Chris Lutz
@chris: please explain why lower numbers are slightly more probable. I cannot see why.
Peter Parker
A: 

Hi

Interpreting your question rather heavily it looks like you want to pseudo-randomly generate 2 different integers between 0 and 9 inclusive ?

So generate the first, generate another, if it's the same as the first repeat until it isn't.

I assert, without justification, that this will be as efficient as any other method.

Regards

Mark

High Performance Mark
and not biased by adding and stuff
High Performance Mark
I wonder how this looks like in PHP code ;)
Zed
A: 
$random1 = rand() % 9;
$random2 = ($random1 + 1) % 9;
codymanix
The second number here will be completely predictable based on the first number.
overstood
The OP only stated that the numbers must not be equal. He never said that the second must be random.
codymanix
+1 because, while a bit cheeky, this is exactly what the op asked for. Although I suppose $random1 = rand() % 9; $random2 = $rand1++; would work just as well ;)
Graham
+2  A: 
$random1 = 4;
$random2 = 5;
overstood
Actually this is quite funny if it's based on that cartoon found here: http://xkcd.com/221/. If it's not based on that, I guess it's *not* so funny :-)
paxdiablo
It is in fact inspired by that comic :-D
overstood
I assure you that there were both randomly generated.
overstood
+2  A: 

I think you'll find that rand()%9 will give you a number in the range 0 through 8 inclusive. If you want 0 through 9 inclusive, you should use rand()%10. I'm going to assume that's what you wanted but you could adjust the answer easily if 0 through 8 was what you really intended.

If you want two numbers in that range, the easiest way is to generate one in that range then generate another in one less than that range and, if it's identical or greater, increment it.

This is the mathematical way to do it, and it's deterministic (always two calls to rand() no matter what). Although unlikely, a true random number generator could produce a string of numbers all identical which would make the looping solutions unwise (you're likely to be using a linear generator so this probably won't be a problem).

On the first attempt, you have the full range to choose from (10 numbers, 0 through 9). On the second you have the full range minus the number already chosen. So, if your first number was 7, you generate a number from 0 through 8 and map 7 to 8 and 8 to 9:

$random1 = (rand() % 10);
$random2 = (rand() % 9);
if $random2 >= $random1 {
    $random2 = $random2 + 1;
}
paxdiablo
This introduces way much dependence between the randoms. If random1 is 5 for example, random2 will have a higher possibility to be 6 than any other number.
Zed
I think if $random2 >= $random1 gives better changes, but maybe I'm missing another edge case.
Kobi
Yeah, you're right @Kobi, that's what I meant to say, but it's late here :-)
paxdiablo
@Zed, that was an artefact of my not writing it down correctly. The probabilities are correct if, as @Kobi points out, you use the correct statements for the mapping.
paxdiablo
@Pax - that should be `$random2 >= $random1`. The way you have it now the odds are still wrong, and the numbers can end up equal.
Kobi
+34  A: 
$r = str_shuffle("0123456789");
$r1 = (int) $r[0];
$r2 = (int) $r[1];
stereofrog
Amazing.. There is a PHP function to do almost anything. Good solution..
Pasta
Wow, that is actually a really neat solution.
Ben Torell
+2  A: 
function random($min, $max) {
    $stack = range($min, $max);
    shuffle($stack); 
    $nr1 = array_pop($stack);
    $nr2 = array_pop($stack);
    return array($nr1, $nr2);
}

This might do the trick without being a math wiz :)

ChrisR
I'd guess `shuffle` is at least linear, so this doesn't scale up too well for `max`. However, this can work well if you need more than 2 distinct random numbers.
Kobi
...more than 2 distinct random integers.
Zed
+1  A: 
$numbers = array_rand(range(0, 9), 2);

echo '<pre>';
print_r($numbers);
echo '</pre>';
Alix Axel
A: 

Alix Axel's solution was the most straightforward and worked fine for me. I wanted three random entries from an existing array, so I used

$rands = array_rand(range(0,count($otherarray)),3);

And then displayed entries for which the key was in $rands.

Amanda