Esta semana trabajando con la generación de ganadores de los sorteos que se realizan en mi empresa, me he topado con un error que hasta ahora no me había pasado nunca. Hasta hace unos días para obtener el boleto ganador, sacaba un número aleatorio entre 1 y el máximo de participaciones, me he dado cuenta que el máximo de participaciones nunca sobrepasaba el número 2.147.000.000 una vez sobrepasado ese número en máquinas de 32 bits (en las de 64 no he probado), se producía un desbordamiento ocasionado por la función rand() y el resultado lo devolvía como número negativo. También probé las alternativas a esta función y con todas obtenía el mismo resultado … desbordamiento.
Por lo tanto me las he tenido que ingeniar para sacar el boleto ganador de otra forma, y este es el código que empleé para ello:
//Nuevo sistema de sorteo para evitar desbordamientos.
$completas =(int) ($participaciones/mt_getrandmax());
$sobrantes = $participaciones – ($completas * mt_getrandmax());
$boleto = $completas * rand(1,mt_getrandmax()) + rand(1, $sobrantes);
Supongamos que $participaciones = 7.000.000.000
Con la función mt_getrandmax() obtenemos el mayor número entero soportado por rand(), en este caso nos devolvía 2.147.000.000. Por lo tanto, $completas = al entero de (7.000.000.000/2.147.000.000) Esto da un resultado de 3.
Ahora necesitamos las participaciones sobrantes, este valor lo obtenemos restandole a las participaciones totales, todas las partes obtenidas: $sobrantes = 7.000.000.000 – (3 * 2.147.000.000). Esto daría = 559.000.000
De esta forma ya podemos operar los valores con rand(). Quedaría así:
$boleto = 3 * rand(1, 2.147.000.000) + rand(1, 559.000.000);

