Why does this function generate pretty randomish numbers?

382 Views Asked by At
// Input: It uses texture coords as the random number seed.
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
// Author: Michael Pohoreski
// Copyright: Copyleft 2012 :-)
float random(float2 p)
{
    // We need irrationals for pseudo randomness.
    // Most (all?) known transcendental numbers will (generally) work.
    float2 r = float2(
        23.1406926327792690,  // e^pi (Gelfond's constant)
         2.6651441426902251); // 2^sqrt(2) (Gelfond–Schneider constant)

    float pDotr = dot(p,r);
    float val = 123456789 % (256 * pDotr + 1e-7);

    return frac(cos(val));
}

When doing some programming on the GPU I've had to use the above code to generate pseudorandom numbers (GPU programming is very limited...), but it's just copy and pasted, could someone explain why the results seem pretty randomish?

I'd rewrite the code mathematically but I don't know how. % finds the remainder when the numbers are divided, and the 'frac' function returns the fractional part of the number (e.g. 4.59 returns 0.59, but -1.75 returns 0.25).

Another thing is that although it's random enough for my uses it's not totally random, e.g.:

enter image description here

Lastly I'm doing this millions of times per second and the function is quite expensive, is there a cheaper way to generate pseudorandom numbers where inputing a stream of values from 0 to 1 will appear random?

2

There are 2 best solutions below

0
On BEST ANSWER

Looks like you might have obtained that code from this StackOverflow answer. You might ask user @Michaelangelo there how his code works. The answer is in response to a question about 3-D computer graphics. Those who use random number for video games and similar things have completely different criteria for their random number generators. Mainly they care about speed and could care less about true randomness or passing any tests for randomness (e.g. the TestU01 Crush tests and the Diehard tests).

If your application actually requires true (pseudo)randomness and you need large numbers of these values before they start to repeat, i.e., $>2^{32}$ or so, then look into the Mersenne Twister algorithm. It's designed for things like Monte-Carlo simulation and is also quite fast. It's the random number generator in Matlab and there are implementations in numerous languages. The Double precision SIMD-oriented Fast Mersenne Twister (dSFMT) C code by the original authors of the algorithm is easy to use and very fast.

0
On

Begin: rant The idea of transcendentals or even irrationals in normal storage on a computer is completely wrong. Every number you can represent in floating point is rational. If you perturb these values by $\pm 10^{-100}$ you will go over infinitely many rationals and irrationals and get the same computer behavior. End: rant

For reals, about the fastest RNG is a linear congruential generator. One multiply, one add, one mod and you are done. It does well generating one random number, but has problems with correlations between the numbers. For some uses, that doesn't matter. For some, it does. "Randomness is in the eye of the beholder", the quote taken from Numerical Recipes which has a good discussion. Obsolete versions are free online. The sequential correlations explain the lines in the image you posted.