Bueno pues como explica el título del post, se me ocurrió hacer algunas ‘mejoras’ en la función random para tener un mayor control sobre los números aleatorios a la hora de trabajar con ellos. Permite introducir intervalos (de momento 2 como máximo, si alguien se ve con ganas y tiempo de mejorarla más para que se puedan meter todos los que hagan falta, adelante, y que por favor nos deje el código aquí (: ) abiertos y cerrados por izquierda y derecha, y hacer uniones y diferencias simétricas (intersecciones no porque con sólo dos intervalos no tiene mucho sentido). Además le he añadido un pequeño prototype al objeto para redondear o mostrar el número resultante, y unas funciones para no tener que poner "Math." cada vez. Por último, señalar que este código está dirigido a redondear el número (se ve bastante bien más abajo XD), así que si alguien usa este código esperando números para usarlos con decimales tendría que modificarlo un poco. Aquí os dejo el código:
Código Javascript
:
Ver originalfunction rnd(){
return Math.random();
}
function round(n){
return Math.round(n);
}
function power(n,x){
return Math.pow(n,x);
}
var minimo, alReves, union, partes, cual, rand, numeros, intervalos, num, i, j, resta, txt, intg, oper;
minimo=(10).power(-16);
alReves = {
'(' : ']',
')' : '[',
'[' : ')',
']' : '('
};
function random(str){
union = /u/i;
rand=rnd();
numeros=[];
if(/[\^u]/i.test(str)){ // varios intervalos
if(union.test(str)){ // unión de intervalos
partes=str.split(union); // separamos por el 'operador'
cual = rand>=(1-minimo)/partes.length?1:0; // decidimos en qué intervalo estará nuestro número
numeros=partes[cual].match(/\d+/g); // cogemos los números que haya en ese intervalo
resta=numeros[1]-numeros[0]; // restamos el menor al mayor
//alert('rand:'+rand+'\ncual:'+cual+'\nbool:'+bool+'\npartes:'+partes.join()+'\nnumeros:'+numeros.join()+'\nresta:'+resta);
rand*=resta; // multiplicamos por la diferencia
rand+=parseFloat(numeros[0]); // sumamos el menor
//alert(rand);
if(rnd()>=(1-minimo)/partes.length) rand+=(cual?-1:1)*resta/2; // para que puedan darse todos los números
if(partes[cual].charAt(0)=='('&&round(rand)==numeros[0]) rand+=0.5; // si es abierto por la izquierda, evitamos que se redondee "mal"
if(partes[cual].lastCharAt(0)==')'&&round(rand)==numeros[1]) rand-=0.5; // si es abierto por la derecha, evitamos que se redondee "mal"
//alert(rand);
}else{
if(/\^/.test(str)){ // diferencia simétrica de conjuntos
var txt='', intg=str.match(/\d+/g), oper=str.match(/[\[\]()]/g); // [ ó ] ó ( ó )
txt+=oper[0]+intg[0]+','+intg[2]+alReves[oper[2]]+'U'+alReves[oper[3]]+intg[3]+','+intg[1]+oper[1];
// colocamos los elementos de los arrays de los match() según convenga
return new random(txt); // devolvemos un new random que cambiará la diferencia simétrica (^) por unión (U)
}
}
}else{ // sólo un intervalo
partes=str.split(','); // separamos el intervalo por la coma
numeros=str.match(/\d+/g); // cogemos los números que haya en ese intervalo
resta=numeros[1]-numeros[0]; // restamos el menor al mayor
rand*=resta; // multiplicamos por la diferencia
rand+=numeros[0]; // sumamos el menor
if(partes[0].charAt(0)=='('&&round(rand)==numeros[0]) rand+=0.5; // si es abierto por la izquierda, evitamos que se redondee "mal"
if(partes[0].lastCharAt(0)==')'&&round(rand)==numeros[1]) rand-=0.5; // si es abierto por la derecha, evitamos que se redondee "mal"
}
this.rand = rand; // asignamos la variable a la propiedad rand del objeto
};
random.prototype = {
ceil : function(){
return Math.ceil(this.rand);
},
floor : function(){
return Math.floor(this.rand);
},
round : function(){
return round(this.rand);
},
show : function(){
alert(this.rand);
}
};
Por cierto, si alguien ve algún error que me lo diga pero hice 2 ó 3 pruebas así:
Código Javascript
:
Ver originalvar aleatorio = new random('[0,8]^[3,7]'), i=0;
while((aleatorio.round()>=0&&aleatorio.round()<3)||(aleatorio.round()>7&&aleatorio.round()<=8)){
i++;
aleatorio = new random('[0,8]^[3,7]'); // número entre 0 y 8 (inclusive) pero no entre 3 y 7 (inclusive)
}
Y así:
Código Javascript
:
Ver originalvar aleatorio = new random('[0,3)u(7,8]'), i=0;
while((aleatorio.round()>=0&&aleatorio.round()<3)||(aleatorio.round()>7&&aleatorio.round()<=8)){
i++;
aleatorio = new random('[0,3)u(7,8]'); // número entre 0 y 8 (inclusive) pero no entre 3 y 7 (inclusive)
}
Y FF me dijo que si quería detener el script porque no respondía (no probé en IE ni Chrome), así que me imagino que no será un fallo muy gordo.
Saludos (: