2009-04-10 10 views
104

¿Cuál es la diferencia entre Math.random() * n y Random.nextInt(n) donde n es un número entero?Math.random() versus Random.nextInt (int)

+0

No sé las matemáticas, pero sé que FindBugs se queja si utiliza 'Math.random()' – finnw

+3

Recuerde que Random no tiene un método estático, a fin de utilizar:. (Nueva aleatorio()) nextInt (norte)). Para que Math genere un entero similar, use: Math.floor ((Math.random() * n) +1); –

Respuesta

138

Aquí es the detailed explanation de por qué "Random.nextInt(n) es más eficiente y menos sesgada que Math.random() * n" de los foros de Sun Post que Gili vinculada a:

Math.random() usa Random.nextDouble() internamente.

Random.nextDouble() usa Random.next() dos veces para generar un doble que tiene bits distribuidos de manera uniforme en su mantisa, por lo que se distribuye uniformemente en el rango de 0 a 1- (2^-53).

Random.nextInt (n) utiliza Random.next() menos del doble en promedio: lo usa una vez, y si el valor obtenido está por encima del múltiplo más alto de n por debajo de MAX_INT lo intenta de nuevo; de lo contrario, devuelve el valor módulo n (esto impide que los valores por encima del múltiplo más alto de n por debajo de MAX_INT sesguen la distribución), por lo que devuelve un valor que se distribuye uniformemente en el rango de 0 a n-1.

Antes de escalar por 6, la salida de Math.random() es uno de los 2^53 valores posibles extraídos de una distribución uniforme.

Escalar por 6 no altera el número de valores posibles, y fundir a un int luego fuerza estos valores en uno de seis 'cubos' (0, 1, 2, 3, 4, 5), cada cubo correspondiente a rangos que abarcan 1501199875790165 o 1501199875790166 de los valores posibles (ya que 6 no es un consejero de 2^53). Esto significa que para un número suficiente de dados (o un dado con un número suficientemente grande de lados), el dado mostrará que está sesgado hacia los cubos más grandes.

Tendrá que esperar mucho tiempo lanzando dados para que aparezca este efecto.

Math.random() también requiere aproximadamente el doble de procesamiento y está sujeto a sincronización.

+3

Random.nextInt y nextDouble también están sujetos a sincronización. – adrianos

+0

En este contexto, ¿qué significa "menos sesgado", por favor? –

+0

@ ΦXocę 웃 Пepeúpa ツ Simplemente significa que es más probable que se dibujen ciertos números que otros. Como está predispuesto a elegir algunos números sobre otros (por lo tanto, no es totalmente aleatorio ni se le da un tamaño de muestra suficientemente grande uniforme) –

26

otro punto importante es que Random.nextInt (n) es repetible ya que se puede crear dos objetos al azar con la misma semilla . Esto no es posible con Math.random().

0

De acuerdo con este ejemplo, Random.nextInt(n) tiene un resultado menos predecible que Math.random() * n. De acuerdo con [matriz ordenada más rápido que una matriz no ordenada] [1], creo que podemos decir que Random.nextInt (n) es difícil de predecir.

usingRandomClass: tiempo: milesecond.

usingMathsRandom: time: milesecond.

package javaFuction; 
import java.util.Random; 
public class RandomFuction 
{ 
    static int array[] = new int[9999]; 
    static long sum = 0; 
    public static void usingMathsRandom() { 
     for (int i = 0; i < 9999; i++) { 
     array[i] = (int) (Math.random() * 256); 
     } 

     for (int i = 0; i < 9999; i++) { 
      for (int j = 0; j < 9999; j++) { 
       if (array[j] >= 128) { 
        sum += array[j]; 
       } 
      } 
     } 
    } 

    public static void usingRandomClass() { 
     Random random = new Random(); 
     for (int i = 0; i < 9999; i++) { 
      array[i] = random.nextInt(256); 
     } 

     for (int i = 0; i < 9999; i++) { 
      for (int j = 0; j < 9999; j++) { 
       if (array[j] >= 128) { 
        sum += array[j]; 
       } 
      } 

     } 

    } 

    public static void main(String[] args) { 
     long start = System.currentTimeMillis(); 
     usingRandomClass(); 
     long end = System.currentTimeMillis(); 
     System.out.println("usingRandomClass " + (end - start)); 
     start = System.currentTimeMillis(); 
     usingMathsRandom(); 
     end = System.currentTimeMillis(); 
     System.out.println("usingMathsRandom " + (end - start)); 

    } 

} 
+1

. En el segundo ciclo, compruebe> = 50, que es cierto en más del 50% de los casos. Eso hará que esta declaración if sea verdadera la mayoría de las veces, lo que la hace más predecible. Por lo tanto, sus resultados están sesgados a favor de su respuesta –

+0

es un error tipográfico ... haga 128 en el segundo ejemplo obtendrá el mismo resultado. –

Cuestiones relacionadas