Strange behaviour of Rand() function

Asked

Viewed 81 times

1

By the definition in documentation

echo rand() // Imprime algo completamente aleatório
echo rand($min, $max) // Imprime algo em um range entre min e max

In a code, inside a loop, I accidentally ended up generating the following rand($max, $min) then I observed the bizarre behavior, it does not generate a warning saying that the value of the first parameter should not be greater than the value of the second, as if for example I omit only one of the values, that would generate me:

E_WARNING : type 2 -- Rand() expects Exactly 2 Parameters, 1 Given

If I use the function mt_rand for example, it generates me the warning:

E_WARNING : type 2 -- mt_rand(): max() is smaller than min()

But with rand generated values with a peculiar behavior that made me curious

Testing for example the following code:

for($j = 0; $j < 10; $j++){
    for($i = 0; $i < 10; $i++){
        if($i < 9) echo rand(10,0).",";
        else echo rand(10,0)." | teste -> ".($j+1)."<br/>";
    }
}

I got about the following:

3,10,4,5,7,8,4,9,5,2 | teste -> 1
2,2,10,5,9,6,8,2,5,2 | teste -> 2
7,8,4,10,5,7,8,8,5,4 | teste -> 3
9,7,4,3,10,10,9,4,8,4 | teste -> 4
5,8,4,4,3,3,8,10,4,3 | teste -> 5
2,9,9,5,8,4,10,5,10,5 | teste -> 6
8,9,10,2,10,9,10,9,2,8 | teste -> 7
2,6,6,5,9,8,7,6,8,9 | teste -> 8
8,8,7,6,2,5,8,2,9,8 | teste -> 9
5,6,6,4,7,6,3,6,4,4 | teste -> 10

And worse! If you change the rand for closer values, like rand(10,8), he prints:

10,10,10,10,10,10,10,10,10,10 | teste -> 1
10,10,10,10,10,10,10,10,10,10 | teste -> 2
10,10,10,10,10,10,10,10,10,10 | teste -> 3
10,10,10,10,10,10,10,10,10,10 | teste -> 4
10,10,10,10,10,10,10,10,10,10 | teste -> 5
10,10,10,10,10,10,10,10,10,10 | teste -> 6
10,10,10,10,10,10,10,10,10,10 | teste -> 7
10,10,10,10,10,10,10,10,10,10 | teste -> 8
10,10,10,10,10,10,10,10,10,10 | teste -> 9
10,10,10,10,10,10,10,10,10,10 | teste -> 10

I tested the following emulators online: repl it., ideone. and phpfiddle.org and I was able to observe that in those that use more current versions of PHP this does not occur, I went deeper and found this emulator that gives to choose old versions: sandbox.onlinephpfunctions.com and saw that until version 7.0.14 this still occurred, I tried to look for something in the changelog php.net and in the official php repository on github but I couldn’t find anything about it.

Finally, of course this is a mistake, and it shouldn’t even exist in code! But a curiosity hit me, what actually happens with the function rand, in older versions of PHP, when a max value is less than min?

  • Syntax error? This doesn’t seem like a structural problem in grammar, so I guess it’s not syntactic. Semantic error?

  • The grammar of the function call is <<fun name>> ( <<lvalue list>> ); the arguments are given by the list <<lvalue list>> ::= <<lvalue>> | <<lvalue>> , <<lvalue list>>, being <<lvalue>> an expression, variable or constant. Then, to know that rand has in its grammar of use rand ( <<minor>> , <<major>> ) with the non-structural rule <<minor>> lesser than <<major>>, would need to know at compile level the values <<minor>> and <<major>> and would also need a different grammatical rule for that function. That’s why I’m talking about semantics

  • In the answer you gave, I believe it is more similar to the example of dividing zero by zero, an operation that in itself does not make sense, but is grammatically correct. Don’t forget: colorless green ideas sleep furiously

  • Anyway, it’s a mistake rs, I don’t want to focus on this mistake, I want to understand why it occurs, see, if I hadn’t paid attention to it, it generates a bizarre result, but "acceptable", that is, it could have been maintained, and I wouldn’t have had random values.

1 answer

1

I read both documents, in English and Portuguese. I can say that there is a very big difference between them. See the documentation in English if you have no problem with English.

I also checked the source code on Github.

Currently, in the latest versions available, calls to the function rand become calls to mt_rand, but he treats max < min specifically to avoid calling mt_rand with the values exchanged.

Have an observation on English commentary on documentation that speaks precisely of the tendency of PHP to generate numbers close to multiples of 3, but I don’t understand the exact reason for this. It seems that another comment tried to explain by blaming the large range of numbers used by the previous.

For the implementation of php_mt_rand_range in C no Github, if the random number generation is low entropy in the least significant bits, the return given by (result % umax) + min (where umax = max - min + 1) will always be similar when the difference between the minimum and the maximum is also small. Judging whether the random number function has high entropy is beyond my knowledge, however, and even beyond my knowledge is judging whether the less significant bits have high entropy.

  • 1

    Note, I tested the code of the comment in that emulator that gives to choose the version of PHP, the result seemed very random in all versions >= 4.4.9, the same comment is 10 years ago.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.