LlFrand

De DigiWiki.

// Tosses a coin, giving a *near* 50:50 chance of a result.
integer coin_toss()
{
  if( llFrand(1.) < .5 ) return TRUE;
  return FALSE;
}
 
// Sometimes it is useful to get a random integer over a given range.  This is a surprisingly tricky and emotive subject
// and has caused endless discussion on the scripting groups.
// The primary cause of probability errors when employing llFrand is to have a varying bin size on the edges of the range.
//
// As the bracket notation indicates, [0.0,'''mag'''), the function is inclusive of the 0.0 and exclusive of the entered value.
// Because an LSL floating point number is only a subset of real numbers and does not have infinite granularity, this schema
// will work for any float greater than float t = 1.175494351e-38; at which value the function will
// return only zero.  At a float beyond this, a math error occurs.
 
// Random integer generator 
// Contributed by Mephistopheles Thalheimer, original function posited by Hg Beeks
 
// Returns a pseudo-random integer in the range of min to max inclusive.
 
// Rationale: Expands the range by 1.0 to ensure equal bin spacing on ends relative to the middle of 
// the range and then uses an integer cast to round towards zero.  
 
// Caveats:  This function is not range checked and will fail if max < min
 
integer random_integer( integer min, integer max )
{
  return min + (integer)( llFrand( max - min + 1 ) );
}
 
default
{
    touch_start(integer total_number)
    {
        // When touched, say "Heads" with probability 0.5, 
        // otherwise, say "Tails."
        if ( coin_toss() )
            llSay(0, "Heads");
        else
            llSay(0, "Tails");
 
        integer n1 = random_integer( 2, 8 ); // Return a random number between 2 and 8
        llSay( PUBLIC_CHANNEL, "I chose a " + (string)n1 );
 
    }
}
// Simple integer random number tester
// Contributed by Mephistopheles Thalheimer
 
// This is a random number tester designed to give a quick visual explanation and proof of why some
// random integer functions just do not work.
// In general, with any random number generator, if you can see a pattern emerging, then chances are, 
// the function is not random.
 
// The test case given "silly_random_integer( .. )" shows the type of pitfalls that can happen. Superficially,
// it would seem like a good candidate.  I thought so, and in fact mooted it in a discussion, however, a bit of thought reveals
// that the first and last bin are only collecting rounded results from half the float space as the rest of the integers.
// They are therefore under-represented in output, and the generator is flawed. 
 
 
integer random_integer( integer min, integer max )
{
  return min + (integer)llFrand( max - min + 1 );
}
 
integer silly_random_integer( integer min, integer max )
{
  return min + (integer)( llRound( llFrand( max - min ) ) );  // Looks good, but does not work
}
 
 
// Simple integer random number tester
// Contributed by Mephistopheles Thalheimer
 
list bins;
 
integer     MIN             = 2;        // The minimum integer you want
integer     MAX             = 5;        // The maximum integer you want
 
integer     NUMBER_OF_TRIES  = 10000;    // The bigger the better.. but slower
 
default
{
    state_entry()
    {
        llSay( PUBLIC_CHANNEL, "Bin tester ready.");
        bins = [];
    }
 
    touch_start(integer total_number)
    {
 
        llSay( PUBLIC_CHANNEL, "Started, be patient" );
 
        integer i;
        integer r;
 
        integer range = MAX - MIN;
 
        for( i = 0; i <= range; ++i )
        {
            bins += [ 0 ];    
        }
 
        integer v;
        integer out_of_range;
 
        for( i = 0; i < NUMBER_OF_TRIES; ++i )
        {
            r = silly_random_integer( MIN, MAX );   // Replace this with the function you are testing
                                                    // Note the output on this one has about 0.5 expected hits on the first and last bin
            //r = random_integer( MIN, MAX );
 
            if( r > MAX || r < MIN )
            {    
               out_of_range++;
            }
            else
            {
               v = llList2Integer( bins, r - MIN );
               bins = llListReplaceList( bins, [ ++v ], r - MIN, r - MIN );
            }
        }
 
        for( i = 0; i <= range; ++i )
        {
            llOwnerSay( "Bin #" + (string)( i + MIN ) + " = " + (string)llList2Integer( bins, i ) );    
        }
 
        llOwnerSay( "Number out of range = " + (string)out_of_range );
    }
}
Outils personnels
  • Cette page a été consultée 652 fois.
donate
Google Ads