Doubt about the MOD operator in PHP

2

I have a PHP code that performs a given calculation, however it is something different from what I expect, I performed the calculations in hand and it did not generate the same result, could someone explain to me why? The code for execution is below:

function bsd_rand($seed) {
return function() use (&$seed) {
    return $seed = (1103515245 * $seed + 12345) % (1 << 31);
};
}

$lcg = bsd_rand(0);
echo "BSD ";
for ($i = 0; $i < 10; $i++)
echo $lcg(), " ";
echo "\n";

The first value results in 12345 , but doing this same calculation on paper did not result in this value, please note:

(1103515245 * 0 + 12345) % (-2147483648) = ?

The result should be -2147471303 and not 12345

    
asked by anonymous 04.03.2015 / 22:13

2 answers

3

The explanation has already been given by @chambelix, it seems that the mod (%) operator does not work very well in PHP for when the "module" of the negative divisor (read the number without the negative sign) is greater than the positive dividend ... Or vice versa, see tests:

echo (12345 % (-2147471303))."\n"; // Retorna 12345 (errado)
echo ((-2147471303) % 12345)."\n"; // Retorna -9173 (errado)

To have a better experience with very large negative values, there is a function that solves the problem:

function truemod($num, $mod) {
  return ($mod + ($num % $mod)) % $mod;
}

echo truemod(12345,-2147471303)."\n"; // Retorna -2147471303 (certo)
echo truemod(-2147471303,12345); // Retorna 3172 (certo)

I honestly think the function you are using is a little confusing ... I would do it this way:

for ($i = 0; $i < 10; $i++){
    $numerador = (1103515245 * $i + 12345);
    $seed = truemod($numerador,-2147471303);
    echo "BSD: " . $seed . "\n";
}
echo "\n";

function truemod($num, $mod) {
  return ($mod + ($num % $mod)) % $mod;
}

In this case: &$seed the & operator functions as a reference to the $seed variable that was passed by the parent function ...

  

/ * I find it kind of crazy to understand this function below, or to see a utility, but ok ... * /

function bsd_rand($seed) {
    return function() use (&$seed) {
        //Retorne essa função, utilizando a mesma referencia de variável que gerou a variável $seed
    }
}

In general, the & $variavel operator in this case acts as a reference ...

Useful links:

What are referrals?

What references do

    
04.03.2015 / 23:19
1

In PHP the % operator refers to:

$a % $b Módulo  Resto de $a dividido por $b.

The module operands are converted to integers (removing the decimal part) before processing ... to which I still add:

O resto de $a % $b é negativo se $a for negativo.

What immediately puts the result that should in your understanding impossible.

Add still that modulus in PHP if the first operand is less than the second, then the value of the first is returned.

    
04.03.2015 / 23:07