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 );
}
}