Foros del Web » Programando para Internet » Javascript »

Función random mejorada

Estas en el tema de Función random mejorada en el foro de Javascript en Foros del Web. 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 ...
  #1 (permalink)  
Antiguo 14/12/2010, 16:39
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 13 años, 10 meses
Puntos: 310
Función random mejorada

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 original
  1. function rnd(){
  2.  return Math.random();
  3. }
  4. function round(n){
  5.  return Math.round(n);
  6. }
  7. function power(n,x){
  8.  return Math.pow(n,x);
  9. }
  10. var minimo, alReves, union, partes, cual, rand, numeros, intervalos, num, i, j, resta, txt, intg, oper;
  11. minimo=(10).power(-16);
  12. alReves = {
  13.  '(' : ']',
  14.  ')' : '[',
  15.  '[' : ')',
  16.  ']' : '('
  17. };
  18. function random(str){
  19.  union = /u/i;
  20.  rand=rnd();
  21.  numeros=[];
  22.  if(/[\^u]/i.test(str)){ // varios intervalos
  23.   if(union.test(str)){ // unión de intervalos
  24.    partes=str.split(union); // separamos por el 'operador'
  25.    cual = rand>=(1-minimo)/partes.length?1:0; // decidimos en qué intervalo estará nuestro número
  26.    numeros=partes[cual].match(/\d+/g); // cogemos los números que haya en ese intervalo
  27.    resta=numeros[1]-numeros[0]; // restamos el menor al mayor
  28.    //alert('rand:'+rand+'\ncual:'+cual+'\nbool:'+bool+'\npartes:'+partes.join()+'\nnumeros:'+numeros.join()+'\nresta:'+resta);  
  29.    rand*=resta; // multiplicamos por la diferencia
  30.    rand+=parseFloat(numeros[0]); // sumamos el menor
  31.    //alert(rand);
  32.    if(rnd()>=(1-minimo)/partes.length) rand+=(cual?-1:1)*resta/2; // para que puedan darse todos los números
  33.    if(partes[cual].charAt(0)=='('&&round(rand)==numeros[0]) rand+=0.5; // si es abierto por la izquierda, evitamos que se redondee "mal"
  34.    if(partes[cual].lastCharAt(0)==')'&&round(rand)==numeros[1]) rand-=0.5; // si es abierto por la derecha, evitamos que se redondee "mal"
  35.    //alert(rand);
  36.   }else{
  37.    if(/\^/.test(str)){ // diferencia simétrica de conjuntos
  38.     var txt='', intg=str.match(/\d+/g), oper=str.match(/[\[\]()]/g); // [ ó ] ó ( ó )
  39.     txt+=oper[0]+intg[0]+','+intg[2]+alReves[oper[2]]+'U'+alReves[oper[3]]+intg[3]+','+intg[1]+oper[1];
  40.     // colocamos los elementos de los arrays de los match() según convenga
  41.     return new random(txt); // devolvemos un new random que cambiará la diferencia simétrica (^) por unión (U)
  42.    }
  43.   }
  44.  }else{ // sólo un intervalo
  45.   partes=str.split(','); // separamos el intervalo por la coma
  46.   numeros=str.match(/\d+/g); // cogemos los números que haya en ese intervalo
  47.   resta=numeros[1]-numeros[0]; // restamos el menor al mayor
  48.   rand*=resta; // multiplicamos por la diferencia
  49.   rand+=numeros[0]; // sumamos el menor
  50.   if(partes[0].charAt(0)=='('&&round(rand)==numeros[0]) rand+=0.5; // si es abierto por la izquierda, evitamos que se redondee "mal"
  51.   if(partes[0].lastCharAt(0)==')'&&round(rand)==numeros[1]) rand-=0.5; // si es abierto por la derecha, evitamos que se redondee "mal"
  52.  }
  53.  this.rand = rand; // asignamos la variable a la propiedad rand del objeto
  54. };
  55. random.prototype = {
  56.  ceil : function(){
  57.   return Math.ceil(this.rand);
  58.  },
  59.  floor : function(){
  60.   return Math.floor(this.rand);
  61.  },
  62.  round : function(){
  63.   return round(this.rand);
  64.  },
  65.  show : function(){
  66.   alert(this.rand);
  67.  }
  68. };
Por cierto, si alguien ve algún error que me lo diga pero hice 2 ó 3 pruebas así:
Código Javascript:
Ver original
  1. var aleatorio = new random('[0,8]^[3,7]'), i=0;
  2. while((aleatorio.round()>=0&&aleatorio.round()<3)||(aleatorio.round()>7&&aleatorio.round()<=8)){
  3.  i++;
  4.  aleatorio = new random('[0,8]^[3,7]'); // número entre 0 y 8 (inclusive) pero no entre 3 y 7 (inclusive)
  5. }
Y así:
Código Javascript:
Ver original
  1. var aleatorio = new random('[0,3)u(7,8]'), i=0;
  2. while((aleatorio.round()>=0&&aleatorio.round()<3)||(aleatorio.round()>7&&aleatorio.round()<=8)){
  3.  i++;
  4.  aleatorio = new random('[0,3)u(7,8]'); // número entre 0 y 8 (inclusive) pero no entre 3 y 7 (inclusive)
  5. }
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 (:
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #2 (permalink)  
Antiguo 14/12/2010, 22:45
 
Fecha de Ingreso: octubre-2010
Mensajes: 83
Antigüedad: 13 años, 6 meses
Puntos: 4
Respuesta: Función random mejorada

No funciona tu funcion.

Sugerencias:
* Usa closures.
* No hagas prototypes.

Errores:
Código:
minimo=(10).power(-16)
deberia ser
Código:
minimo = power(10, -16)
Tu funcion power deberia ser (si es que la quieres usar de esa manera (10).power(-16))
Código:
Number.prototype.power = function () {
    return Math.pow(this, arguments[0]);
}
aunque mejor seria que lo invpower(10, -16)

Firefox te dice eso porque estas en un bucle infinito.
Tu lastCharAt existe esa funcion? hasta donde se javascript no posee ese metodo, de todas formas eso te da un error.
  #3 (permalink)  
Antiguo 15/12/2010, 00:44
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 13 años, 10 meses
Puntos: 310
Respuesta: Función random mejorada

Lo siento, esque tengo más funciones en el documento porque era uno de prueba y no me di cuenta de si las copiaba todas o no, creo que son estas las que faltan (lastCharAt no existe, la 'inventé' yo para este script):
Código Javascript:
Ver original
  1. Number.prototype.power=function(pwr){
  2.  return Math.pow(this, pwr);
  3. }
  4. String.prototype.lastCharAt=function(position){
  5.  return this.charAt(this.length-1-position);
  6. }
Si falta alguna más avisad xD
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red
  #4 (permalink)  
Antiguo 15/12/2010, 02:46
 
Fecha de Ingreso: octubre-2010
Mensajes: 83
Antigüedad: 13 años, 6 meses
Puntos: 4
Respuesta: Función random mejorada

_cronos2, pega todo tu codigo en jsfiddle [1], lo guardas y pones aca el link que te genera (sale en barra de direcciones).

Ah y no uses while para testear.

[1]: http://jsfiddle.net/
  #5 (permalink)  
Antiguo 15/12/2010, 12:10
Avatar de _cronos2
Colaborador
 
Fecha de Ingreso: junio-2010
Mensajes: 2.062
Antigüedad: 13 años, 10 meses
Puntos: 310
Respuesta: Función random mejorada

Aquí está el enlace.
__________________
" Getting older’s not been on my plans
but it’s never late, it’s never late enough for me to stay. "
Cigarettes - Russian Red

Etiquetas: random
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 21:53.