ircmaxell/RandomLib

Rand Improvement

olekukonko opened this issue · 0 comments

Assumption:
  • I want to assume that you are using % 256 because you want to limit the generated numbers between 0 - 256 ;
Observation 1:

If that is true rand() ^ rand() % 256 would be wrong because of Operator Precedence

Arithmetic comes before bitwise so basically what you are writing is :

rand() ^ (rand() % 256)
Observation 2:

If what you intend to accomplish is

(rand() ^ (rand()) % 256

It would not be efficient on windows platform because of the use of Linear Congruential Generator. It can be improved with:

(rand() ^ (rand() / getrandmax())) % 256;

Here is a simple test script

$results = array(
        "m1" => 0,
        "m2" => 0
);

$repeat = ceil(256 / 2); // 50 - 50 ;

for($i = 0; $i < $repeat; $i ++) {
    foreach($results as $k => $no) {
        $results[$k] += $k($repeat);
    }
    if ($i == 0) {
        printf("First Run\n%s\n\n", json_encode($results, 128));
    }
}

printf("$repeat Runs\n%s\n", json_encode($results, 128));

function m1($x) {
    $data = array();
    $collision = 0;
    for($i = 0; $i < $x; $i ++) {
        $n = (rand() ^ (rand() / getrandmax())) % 256;
        if (isset($data[$n])) {
            $collision ++;
        } else {
            $data[$n] = 0;
        }
        $data[$n] ++;
    }
    // rsort($data);
    // var_dump($data);
    return $collision;
}

function m2($x) {
    $data = array();
    $collision = 0;
    for($i = 0; $i < $x; $i ++) {
        $n = (rand() ^ rand()) % 256;
        if (isset($data[$n])) {
            $collision ++;
        } else {
            $data[$n] = 0;
        }
        $data[$n] ++;
    }
    // rsort($data);
    // var_dump($data);
    return $collision;
}
Output
First Run
{
    "m1": 0,
    "m2": 99         <--- Collision on your method
}

128 Runs
{
    "m1": 0,
    "m2": 12672      <--- Collision on your method
}
  • Windows 7 Ultimate Edition Service Pack 1) i586
  • PHP Version 5.4.14
  • API220100525,TS,VC9