Difference between revisions of "Pseudo-random Number Generator"

From Second Life Wiki
Jump to navigation Jump to search
m
(Brushed up and added to category index)
Line 10: Line 10:




<pre>
<lsl>
// IMPORTANT: Change the following numbers before using!
// IMPORTANT: Change the following numbers before using!
integer seed1 = 0x053FA20C;
integer seed1 = 0x053FA20C;
Line 25: Line 25:
}
}


</pre>
</lsl>
The below code is exactly the same as the above, only it is much faster. Thanks to Strife Onizuka.
The below code is exactly the same as the above, only it is much faster. Thanks to Strife Onizuka.
<pre>
<lsl>
integer rand(integer spread) {
integer rand(integer spread) {
     seed2 = (seed2 * seed2Mod + 0xB);
     seed2 = (seed2 * seed2Mod + 0xB);
return (seed1Mod = ((seed1 = (seed1 * (seed2Mod = seed1Mod) + 0xB)) * seed2)) % spread;
return (seed1Mod = ((seed1 = (seed1 * (seed2Mod = seed1Mod) + 0xB)) * seed2)) % spread;
}
}
</pre>
</lsl>
Example code to test the randomness (Is that a word?) of the generator.
Example code to test the randomness (Is that a word?) of the generator.
<pre>
<lsl>
default {
default {
state_entry() {
state_entry() {
Line 58: Line 58:
}
}
}
}
</pre>
</lsl>


Note: A pattern of digits like yyyymmddnn often works as a seed that changes often enough, ''e.g.'', test with 2007090103 == 2,007,090,103 as the 3rd try of the 1st day of the 9th month of the 2007th year, except you must take care to avoid confusing yourself with integers larger than the 2,147,483,647 limit of 32-bit signed arithmetic.
Note: A pattern of digits like yyyymmddnn often works as a seed that changes often enough, ''e.g.'', test with 2007090103 == 2,007,090,103 as the 3rd try of the 1st day of the 9th month of the 2007th year, except you must take care to avoid confusing yourself with integers larger than the 2,147,483,647 limit of 32-bit signed arithmetic.
Line 64: Line 64:
Note: Google Groups sci.math cites Knuth & Lewis suggesting the following linear congruential generator for 32-bit arithmetic processors. Someone skilled in the relevant mathematics should be able to prove that these choices of multiplier and addend provides results that feel more random. Someone skilled in Google might find yet more popular choices than these. People say the choose function returning the quotient rather than the remainder matters: try counting odd results and even results from the pseudorandom() routine to see why.
Note: Google Groups sci.math cites Knuth & Lewis suggesting the following linear congruential generator for 32-bit arithmetic processors. Someone skilled in the relevant mathematics should be able to prove that these choices of multiplier and addend provides results that feel more random. Someone skilled in Google might find yet more popular choices than these. People say the choose function returning the quotient rather than the remainder matters: try counting odd results and even results from the pseudorandom() routine to see why.


<pre>
<lsl>
integer seed = 2007090103;
integer seed = 2007090103;


Line 104: Line 104:
     }
     }
}
}
</pre>
</lsl>
 
{{LSLC|Library}}

Revision as of 06:43, 11 December 2007

See also: llFrand, llListRandomize, Seedable_PRNG

Seedable PRNG Based On Multiply/ Add/ Overflow

Here's a Pseudo-random Number Generator - I (Xaviar Czervik) just made it up off the top of my head - so it has no mathematical research behind it to prove it's random... I've tested it for a while and it looks random to me, about the same as llFrand(). But what ever. Sue me. The main reason that I use it so that I can test scripts, and then when it blows up because of a math error, I can just run the script again an it will use the same numbers, in the same order.

I use this for determining a random channel for two (or more) objects to talk on. This allows the scripts to talk without users being able to intercept the messages - and even if they do - then the channel will change in a minute or two - so no harm done.


<lsl> // IMPORTANT: Change the following numbers before using! integer seed1 = 0x053FA20C; integer seed2 = 0x3B1264D5; integer seed1Mod = 0x71B5F252; integer seed2Mod = 0x56A0E61D;

integer rand(integer spread) {

   	seed1 = (seed1 * seed1Mod + 0xB);
   	seed2 = (seed2 * seed2Mod + 0xB);
       seed2Mod = seed1Mod;
       seed1Mod = seed1 * seed2;

return seed1Mod % spread; }

</lsl> The below code is exactly the same as the above, only it is much faster. Thanks to Strife Onizuka. <lsl> integer rand(integer spread) {

   	seed2 = (seed2 * seed2Mod + 0xB);

return (seed1Mod = ((seed1 = (seed1 * (seed2Mod = seed1Mod) + 0xB)) * seed2)) % spread; } </lsl> Example code to test the randomness (Is that a word?) of the generator. <lsl> default { state_entry() { integer i = 0; integer min = 0x7FFFFFFF; integer max = -0x7FFFFFFF; integer total = 0; while (i < 100000000) { integer r = rand(0x7FFFFFFF); if (r < min) { min = r; } if (r > max) { max = r; } total += r; i++; } llOwnerSay("Min: " + (string)min); llOwnerSay("Max: " + (string)max); llOwnerSay("Average: " + (string)(total/100000000));

} } </lsl>

Note: A pattern of digits like yyyymmddnn often works as a seed that changes often enough, e.g., test with 2007090103 == 2,007,090,103 as the 3rd try of the 1st day of the 9th month of the 2007th year, except you must take care to avoid confusing yourself with integers larger than the 2,147,483,647 limit of 32-bit signed arithmetic.

Note: Google Groups sci.math cites Knuth & Lewis suggesting the following linear congruential generator for 32-bit arithmetic processors. Someone skilled in the relevant mathematics should be able to prove that these choices of multiplier and addend provides results that feel more random. Someone skilled in Google might find yet more popular choices than these. People say the choose function returning the quotient rather than the remainder matters: try counting odd results and even results from the pseudorandom() routine to see why.

<lsl> integer seed = 2007090103;

integer pseudorandom() {

   seed = 1664525 * seed + 1013904223;
   return seed;

}

integer choose(integer count) {

   integer nonnegative = 0x7fffFFFF;
   integer choice = pseudorandom() & nonnegative;
   return ((choice / (nonnegative / count)) % count);

}

default {

   state_entry()
   {
       string line;
       integer index;
       line = "";
       for (index = 0; index < 9; ++index)
       {
          line += " " + (string) pseudorandom();
       }
       llOwnerSay(line);
       line = "";
       for (index = 0; index < 30; ++index)
       {
          line += " " + (string) (1 + choose(6));
       }
       llOwnerSay(line);
       llOwnerSay("OK");
   }

} </lsl>