3
\$\begingroup\$

I'm currently working on a galaxy generator, and I was in need of getting the next that a random would use, for continuing the generation without using a blank generation (re-run previous generation).

I made this little PHP class to do that and implemented a float rand() method.

Please provide advice on improvements.

<?php

namespace Classes;

define('GC_RAND_MAX',   0x7fffffff);

class Random
{   
    private $seed = 1;

    public function setSeed($seed) {
        $this->seed = $seed;
    }

    public function getSeed() {
        return $this->seed;
    }

    public function rand($min = 0, $max = 0) {
        $this->seed = ($this->seed * 1103515245 + 12345) & GC_RAND_MAX;
        $number = (($this->seed >> 1) & GC_RAND_MAX);

        if ($min > $max) { $min = $max; $max = $min; }
        else { $min = $min; $max = $max; }
        if ($max - $min)
            $number = ($number % ($max + 1 - $min)) + $min;

        return $number;
    }

    public function getRandMax(){
        return GC_RAND_MAX;
    }

    public function floatRand($Min, $Max, $round = 0) {
        //validate input
        if ($Min > $Max) { $Min = $Max; $Max = $Min; }
        else { $Min = $Min; $Max = $Max; }

        $range = $Max - $Min;
        $randomfloat = $Min + $range * ($this->rand() << 4 & $this->rand()) / (GC_RAND_MAX >> 1);

        if($round > 0)
            $randomfloat = round($randomfloat, $round);
        return $randomfloat;
    }
}
\$\endgroup\$
2
\$\begingroup\$

You haven't documented your pseudorandom generators. This makes reacting to the code a lot harder. What algorithm are you trying to use? Mersenne Twister? Lehmer? Inversive congruential? Linear congruential? Middle square? Your own?

I've dabbled a bit, in the past, with writing random generators myself. I have concluded two things:

  • It is a lot harder, to get right, than it looks. Books have been written about this.
  • If you write your own generator you have to analyse its output. How random is it really? https://www.random.org/analysis

I would strongly advise to use an existing algorithm, and document this in your code, with references. In all other cases use a built-in generator, PHP has several. You've already seen that rand() isn't the best, but you could use:

http://php.net/manual/en/function.random-int.php

Note that they document the used algorithm. If you use Linux then the generator relies on entropy gathered from device drivers and other sources of environmental noise, which is a better way to get 'truly' random results, because it is less deterministic.

As for your code, I noticed that you use this line twice:

if ($min > $max) { $min = $max; $max = $min; }

This is overkill when the following will do:

if ($min > $max) $min = $max;

This does not increase my confidence in the quality of your generators.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.