Sameet has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
is it possible to select a random number from an array containing 181014922 elements or even higher number of elements, something like 3,020,300,000. can PERL do that, or it has to be done in a complicated manner. regards sameet.

Regarding this I have actually written a longish program, I actually need to add one more nested loop in each elsif loop, I am pasting the code for reference. If there is a easier way out Please tell me

#!/usr/bin/perl use strict; #use warnings; use BeginPerlBioinfo; srand ($$|time); my $contig; # This program will download the sequences from a given organism my $organism; print "Give the organism from where you want to download the sequences +:\n"; $organism = <STDIN>; chomp $organism; #print "Give number of sequences to be generated"; #print "\n"; my $number = 10; #chomp $number; my @numbers = (1 .. $number); foreach my $numbers(@numbers){ if ($organism eq 'Homo Sapien'){ my @chromosomes = qw\1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + 18 19 20 21 22 'X' 'Y'\; # pick a random chromosome from the chromosomes in humans my $chromosome = random_element(@chromosomes); #my $contig; print "Chromosome $chromosome\n"; # pick up a contig randomly from the number of contigs present + in each given chromosome # This is one more loop if ( my $chomosome eq '1'){ my @contigs = (1 .. 30); my $contig = random_element(@contigs); } elsif ($chromosome eq '2'){ my @contigs = (1 .. 28); my $contig = random_element(@contigs); } elsif ($chromosome eq '3'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '4'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '5'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '6'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '7'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '8'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '9'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '10'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '11'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '12'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '13'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '14'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '15'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '16'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '17'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '18'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '19'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '20'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '21'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq '22'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } elsif ($chromosome eq 'X'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs) } elsif ($chromosome eq 'Y'){ my @contigs = (1 .. 25); my $contig = random_element(@contigs); } print " Contig $contig \n"; } } ################ # ############## # random_element # # Sub routine thta picks up random element from a given array sub random_element{ my @array = @_; return $array [rand @array]; }

janitored by ybiC: Balanced <readmore> tags around longish codeblock, especially for frontpaged root node. Also wee tiny format tweaks for legibility.

Replies are listed 'Best First'.
Re: What is the limit of random number that can be selected
by BrowserUk (Patriarch) on Apr 23, 2004 at 21:31 UTC

    If you need a really good random number generator take a look at Math::Random::MT. It appears to have a very well tested pedigree (within my limited ability to judge such things), it is a drop-in replacement for the standard (pretty good) PRG, and when I first investigated, it easily stood up to some fairly extensive specteral testing I did (Re: Testing for randomness (spectral testing)) a while back (I ran my test in the background continuously for well over a week!).


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
Re: What is the limit of random number that can be selected
by matija (Priest) on Apr 23, 2004 at 19:06 UTC
    Yeah, it can:
    perl -e 'foreach (1..20) {print rand(2**40)."\n";}' 652134293073.004 1052236192611.47 192842278698.137 607110319202.945 169022882701.082 527530860527.984 927864292758.34 1056669509421.09 334346614774.41 928276890176.75 1007499895313.79 947274310133.477 99715725600.9883 844160053849.766 826658965072.496 492702127712.117 518596741600.816 70972611711.0312 56473002822.4492 357827335249.008
    Use the int function to get integers.
      You have at least a 48-bit random number generator, so count yourself lucky. Even so, if you change your 40 to a 49, you might find that all twenty of your values are even numbers, as it is on my machine. So taking the number modulo a few billion leaves you with potential skewings of about one part in 65,000 or so. That's good enough for many, but not all, applications.
Re: What is the limit of random number that can be selected
by Belgarion (Chaplain) on Apr 23, 2004 at 19:09 UTC

    Assuming your perl binary was compiled with enough RANDBITS and that you can store the entire array in memory, than yes, you can pull out a random element of the array.

    For example, the following code generates an array with 100 elements in it, and retrieves the value of one element randomly selected:

    my @a = map { rand(10) }(1..100); print $a[int(rand(100))]; __OUTPUT__ 4.65349565896584

    You should be able to do something similar, except that your array would be bigger. Basically, the amount of memory would determine whether Perl could handle the process.

Re: What is the limit of random number that can be selected
by sgifford (Prior) on Apr 23, 2004 at 22:04 UTC
    As others have said, how big of a random number Perl can generate natively depends on how many RANDBITS you compiled with. But you should be able to multiply several random numbers together, up to the biggest integer size your system supports.
      Great,but how do i find out with how many RANDBITS was Perl compiled on my computer.
        use Config; print $Config{randbits};

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
Re: What is the limit of random number that can be selected
by astaines (Curate) on Apr 24, 2004 at 19:41 UTC

    Few comments - your inner loop could be replaced by a hash look up. Put the number of contigs on each chromosome into a hash indexed by chromosome, and pull the limits of the loop from there. This scales better, and is far easier to extend to other organisms.

    Also, generating very large random numbers is always difficult. You are very likely to run across machine and architecture specific problems.A simpler solution is to generate two random numbers, one which selects a segment of the database, array or whatever you're getting your stuff from, and a second which selects the specific item.

    Whether this is what you want depends on your application. Go ask your friendly statistician.

    -- Anthony Staines
      Can you show my via an example. Actually, i am very bad at coding!!!
      thanks
      --Sameet

        Heres how I would code what you have already:

        #!/usr/bin/perl use strict; use warnings; #use BeginPerlBioinfo; srand($$|time); my $data = { 'Homo Sapien' => { Chromosomes => { (map { $_ => {Contigs => 25} } (1..22, qw/X Y/)), # Auto g +en 1 => {Contigs => 30}, # Override these two.. 2 => {Contigs => 28}, }, }, }; # This program will download the sequences from a given organism my $organism = ask('Which organism would you like to download the '. 'sequences from?'); #my $organism = 'Homo Sapien'; my $number = ask("How many sequences do you want to generate?"); #my $number = 10; if (exists $data->{$organism}) { for (1..$number) { my $chromosome = random_element(keys%{$data->{$organism}{Chrom +osomes}}); print " Chromosome '$chromosome' \n"; my $contig = random_element( (1..$data->{$organism}{Chromosomes}{$chromosome}{ +Contigs}) ); print " Contig '$contig' \n"; } } else { print "I don't know anything about organism: '$organism'\n"; } exit; ################ # ############## # ask # # Sub which asks a given question and returns the chomped input from t +he user sub ask { my $query = shift; print $query, ":\n"; my $answer = <STDIN>; chomp $answer; return $answer; } # random_element # # Sub routine that picks up random element from a given array sub random_element{ # I think there's a problem with the randomness of this return $_[int rand(0+@_)]; }
Re: What is the limit of random number that can be selected
by fglock (Vicar) on Apr 26, 2004 at 16:26 UTC

    This code works by concatenating some random numbers, and then scaling the result to the appropriate size:

    use strict; my $max = 3020300000; for ( 1 .. 10 ) { my $rnd = ""; my $div = "1"; for ( 0 .. length($max)/3 ) { $rnd .= sprintf( "%03d", int( rand( 1000 ) ) ); $div .= "000"; } my $return = int( $max * $rnd / $div ); print "$return\n"; } __END__ Output: 621716507 1535231762 2578709376 1912855527 1226418624 36225623 1231223131 1602498674 2831739360 1587564592