in reply to Generating random 6 digit numbers

#!perl -w @nums = 100000 .. 999999; # Generate all the possible numbers ## Shuffle them (use a better rand if needed) $_ ne ($a=int( rand( $#nums-$_+1))+$_) and $nums[$_] ^= $nums[$a] ^= $ +nums[$_] ^= $nums[$a] for (0..$#nums); print pop@nums; # pop a new one each time you need it

The array takes about 50 seconds to initialise and shuffle (on my quite whimpy box) but much less storage than using a hash of the same size.

There are less obfu versions of the Fisher-Yates shuffle around too, but this one was handy.

Update: Having read your later posts regarding using the numbers during different runs of the program, I realise you need to save the array somewhere.

Not having made any use of the available persistant storage mechanisms that perl provides, I'd probably do something like:

#!perl -w @nums = 100000 .. 999999; # Generate all the possible numbers ## Shuffle them (use a better rand if needed) $_ ne ($a=int( rand( $#nums-$_+1))+$_) and $nums[$_] ^= $nums[$a] ^= $ +nums[$_] ^= $nums[$a] for (0..$#nums); open OUT, '>randoms' or die $!; print OUT pack 'I*', @numbs; close OUT or warn $!;

And then whenI needed one of them

.... open RNDNUM, '<randoms' or die $!; binmode(RNDNUMS); # If needed! seek RNDNUMS, -4, 2; my $newlen = tell RNDNUM; my $rndnum = do { local $/=\4; unpack 'I',<RNDNUM>; } truncate RNDNUM, $newlen or die $!; close RNDNUM or warn $!; ..... # do whatever with $rndnum

... but that's cos I know how to make this work. The second bit of code is untested, but demos the basic mechanism of pre-generating your random numbers and storing them somewhere, and then throwing them away once you've used them.

Whatever you do, don't generate a random number and then try to verify whether you've used it before. That's a recipe for disaster wasteful.

It will seem ok at first, but once your halfway through your range, you are going to (statistically) have to generate 450,000 random numbers before you find one that you haven't used before!

(I just KNOW a mathematician is gonna correct that last bit:)

Updated: removed falacious Infinite Improbability Drivel* cos the mathematician did!

With apologies to Douglas Adams RIP


What's this about a "crooked mitre"? I'm good at woodwork!

Replies are listed 'Best First'.
Re: Re: Generating random 6 digit numbers
by Anonymous Monk on Aug 25, 2002 at 18:42 UTC
    Whatever you do, don't generate a random number and then try to verify whether you've used it before. That's a recipe for disaster. It will seem ok at first, but once your halfway through your range, you are going to (statistically) have to generate 450,000 random numbers before you find one that you haven't used before! (I just KNOW a mathematician is gonna correct that last bit:)

    If you have an urn with 50 blue marbles (representing already seen), and 50 red marbles (not yet seen), do you really think that the average number of draws (with replacement) that you need to make in order to choose a red marble is anywhere near 50? (remember, at this point the probability of drawing a red marble on a given draw is still a relatively high 0.5)
    :-)

      I knew it:) I just KNEW!

      Ok. Worst case scenario, you pick 51 balls before getting a red one. Best case, 1. so that makes the average number 26?

      In the original example, ~225,000 before getting an unused one?

      Update:

      Bah! Having submited this, I suddenly remember drawing dozens and dozens of bell-shaped graphs. I've a sneaky suspicion they've something to do with this!

      I'm gonna stick to nice comfortable metrics like "lots" in future:^p


      What's this about a "crooked mitre"? I'm good at woodwork!
        Actually, worst case scenario would be not drawing a red marble before the heat death of the universe, but that would be extraodinarily improbable. Actually, with 50 blue and 50 red marbles, the average number of draws to get a red marble is just 2. In fact, the probability of 10 or more draws without finding a red marble is less than 0.001. When the ratio of blue to red is 90:10, the average number of draws to pull a red is only 10 (and the probability of more than 50 draws without a red is around .005).
        You nailed the reason why the average was wrong by speaking of the bell-shaped graphs, its more of a weighted average. The chance of not getting the ball you want after 1 pull is 1/2. After 2 pulls it is (50/100)*(50/99), the chance of you missing it the first time times the chance of you missing it the second time (99 because one ball is now out of the running). The chance of you pulling 49 balls out and still not getting the one you want is (50/100)*(50/99)*(50/98)*...*(50/51) which is about 2.9*10^(-9). It *could* happen, it just likely will not.

        On a side note, this is my first node that's not a question! I'm so happy I could cry! Would that people would ask more math based questions so I could actually answer them ^_^. ~Adam
Re: Re: Generating random 6 digit numbers
by ehdonhon (Curate) on Aug 26, 2002 at 04:28 UTC
    @nums = 100000 .. 999999; # Generate all the possible numbers

    I guess it depends on what is meant by "6 digit number". If it means "a number more than the greatest 5 digit number (99,999) but less than the least 7 digit number (1,000,000)", which is probably the case, then this works.

    The other possible definition is "A combination of numbers 0 through 9 taken 6 times." In that case, you could do this:
    @numbs = '000000' .. '999999';

      Hmmm! By that definition, we could all say we earned a 6-digit salary, even if it was $000,000.00.


      What's this about a "crooked mitre"? I'm good at woodwork!