Doubt about the MOD operator in PHP

Asked

Viewed 588 times

2

I have a code PHP that performs a certain calculation, however it is resulting something different than I expect, I performed the calculations in hand and did not generate the same result, anyone could 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 such value, note:

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

The result should be -2147471303 and not 12345

  • I liked the currying

  • 1

    Could you explain why the expected result is -2147471303 and not 12345, just to better understand your line of reasoning? In other words, how did you calculate "manually"?

2 answers

3


The explanation has already been given by @chambelix, apparently, the operator mod (%) does not work very well in PHP when the negative divisor "module" (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)

Honestly, I think the function you’re using is somewhat confusing.... I would do it that 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 that case: &$seed the operator & acts as a reference to the variable $seed which was passed by the parent function...

/* I think it’s crazy to understand this function below, or 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 operator & $variavel then acts as a reference...

Useful links:

What are references?

What references do

  • I will perform a quick java test and check if the same problem happens, just a minute.

  • In java, oddly it gives me 0.

  • Sorry, I got the syntax wrong, it all worked correctly, but I still don’t understand why this result, using Seed as 12345 it does not generate the same result obtained by hand.

  • In fact, in Java only the first 3 results are generated according to the software above, but I think this has to do with that & in front of the Seed passed as parameter.

  • @Danlucioprada edited my answer with an idea for its function...

  • but using this PHP truemod they result me something different than expected, I really need those values, why at a given time it generates me 68, which is a low number, with this truemod it generates very large values in all cases, It leaves the context, I need to understand what is going on in the function, why it is auto returning, and why of the passage of the Seed as parameter have a & in front, what it means. Excuse my insistence, I’m just a student looking for answers =D

Show 1 more comment

1

No PHP the operator % refers to:

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

where 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.

Which puts right away the result that should in its impossible view.

Add even though the modulus in PHP if the first operand is lower than the second, then the value of the first operand is returned.

  • Right, but what does & before the Seed variable passed as parameter mean? And why it returns the function itself.

  • 1

    Means you are passing the variable as a reference and not as a value

  • I say this, because exact, using the positive number, I get the first results from 12345, however already in the second operation the result does not close, for example, Seed in the second pass of for vale the previous value, 12345, and performing the calculation it returns -740551042, but making in the hand results 1485236941

  • Is it passed as a reference? As such, what value is it receiving?

  • which means you are passing the address of that variable and not its value if you put an echo "<br>",":",$Seed,":"; before Return you can evaluate its value which can only be "EMPTY"

  • It has not yet been fully clarified, after all my problem still persists, even using the positive module, only the first value beats, perform the same calculation using as Seed = 12345, and compare with the value generated by the code.

Show 1 more comment

Browser other questions tagged

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