2011-11-14 22 views
6

necesito su ayuda y por favor, dame un consejo. De la programación de las perlas que conozco que para generar entero aleatorio de 30 bits debemos escribir así:generar aleatoria de 64 bits número entero

RAND_MAX*rand()+rand() 

Pero lo que podríamos hacer yo para generar no 30, pero entero de 64 bits aleatorios en su lugar? Creo que es un método muy ineficiente si multiplico dos enteros de 30 bits y luego multiplico nuevamente el entero de 4 bits, entonces, ¿qué tipo de método debo usar? Estoy usando ahora popcount_1 método diferente para 64 bit uno y me gustaría probarlo en enteros aleatorios (también estoy midiendo el tiempo que cada uno lleva para realizar la tarea)

+0

También puede cambiar y agregarlos .. – duedl0r

Respuesta

3

Esto podría ser una solución, sin multiplicación:

r30 = RAND_MAX*rand()+rand() 
s30 = RAND_MAX*rand()+rand() 
t4 = rand() & 0xf 

res = (r30 << 34) + (s30 << 4) + t4 
+1

Esto supone que 'RAND_MAX' es 1 << 15. Si asumes esto, ¿por qué no? 'Rand() + rand() << 15 + rand() << 30 + rand() << 45 + (rand() & 0xf) << 60 '? No hay multiplicaciones en absoluto. – MSalters

+1

¿Por qué no hacer algo como 'return ((unsigned long long) rand() << 48) | ((unsigned long long) rand() << 32) | ((unsigned long long) rand() << 16) | ((unsigned long long) rand() & 0xffff); '? Aquí no tienes multiplicaciones, solo cambios. –

+0

Aunque, sí, puede generar 64 bits Me parece que la resolución del número aleatorio generado no puede ser mayor que el número aleatorio inicial. – Cris

2

Un 64 bits aleatorio es esencialmente 64 bits aleatorios interpretados como un int.

Rellene un conjunto de bytes de longitud 8 con bytes aleatorios (see here for how) e interprete estos como un int (see here for how).

+3

Tengo la sospecha de que con la mayoría de las implementaciones de 'rand() 'usted * no * obtendrá una distribución particularmente uniforme haciendo eso. – Flexo

3

Si boost es una opción, usted podría utilizar boost random.

+0

¿estás seguro de que puede generar 64 bits? Su enlace indica otra cosa: "mt19937 produce enteros en el rango [0, 2^32-1]". – duedl0r

+0

Eche un vistazo a los diversos generadores (http://www.boost.org/doc/libs/1_47_0/doc/html/boost_random/reference.html#boost_random.reference.generators), por ejemplo en 'ranlux64_3'. –

+1

@ duedl0r Si genera un buen valor aleatorio durante todo el intervalo '[0, 2^32-1]', entonces sería bastante trivial combinar dos llamadas para generar un buen valor aleatorio de 64 bits. (Para una definición suficientemente amplia de "bueno", por supuesto. El generador básico aún necesita un período de 2^64 o más, o habrá una gran cantidad de valores que nunca se pueden generar.) –

7

En primer lugar, tengo mis dudas acerca de la solución de publicar un número entero 30 bits. RAND_MAX sí mismo podría ser un valor 31 bits, y RAND_MAX * rand() + rand() es probable que desbordarse, produciendo un comportamiento indefinido (y en la práctica, los valores negativos).

Si necesita un valor mayor que el mínimo garantizado de RAND_MAX o para el caso, cualquier cosa que no es significativamente más pequeño que RAND_MAX, la única solución será utilizar las llamadas sucesivas a rand(), y combinar la valores, pero debe hacerlo con cuidado, y validar los resultados. (. La mayoría de las implementaciones de rand() uso generadores congruentes lineales, que aunque adecuado para algunas tareas, no son particularmente bueno en este caso) de todos modos, algo así como:

unsigned 
rand256() 
{ 
    static unsigned const limit = RAND_MAX - RAND_MAX % 256; 
    unsigned result = rand(); 
    while (result >= limit) { 
     result = rand(); 
    } 
    return result % 256; 
} 

unsigned long long 
rand64bits() 
{ 
    unsigned long long results = 0ULL; 
    for (int count = 8; count > 0; -- count) { 
     results = 256U * results + rand256(); 
    } 
    return results; 
} 

(El código en rand256 está diseñado para eliminar el sesgo de otro modo inevitable se obtiene cuando el mapeo de los valores RAND_MAX a 256 valores)

+0

¿Cómo controlo la precisión en este código? Digamos que quiero generar números aleatorios de 61 bits en lugar de 64 bits. Creo que si empiezo el conteo de 7 en lugar de 8, obtendría un número aleatorio de 56 bits. ¿Estoy en lo cierto? – arunmoezhi

+2

@arunmoezhi Si puede generar 64 bits aleatorios, puede generar 61 generando 64 y tirando 3; p.ej. al enmascarar los tres bits superiores. –

+0

tiene sentido. Gracias. Tu solución se ve bien Pero sería más útil si puede agregarle algunas explicaciones. Me tomó algo de tiempo entender lo que estabas haciendo. – arunmoezhi

1

Una solución genérica:.

template <unsigned long long I> struct log2 { 
    static const int result = 1 + log2<I/2>::result; 
}; 
template <> struct log2<1> { 
    static const int result = 0; 
}; 

template <typename UINT> UINT genrand() { 
    UINT result = 0; 
    int bits = std::numeric_limits<UINT>::digits; 
    int rand_bits = log2<RAND_MAX>::result; 
    while (bits > 0) { 
    int r = rand(); 
    while (r >= (1<<rand_bits)) r = rand(); // Retry if too big. 
    result <<= rand_bits; 
    result += r; 
    bits -= rand_bits; 
    } 
    return result; 
} 

Uso: unsigned long long R = genrand<unsigned long long>();.

El contador bits rastrea el número de bits necesarios todavía.

0

'devuelve un valor integral pseudo-aleatorio entre 0 y RAND_MAX (0 y RAND_MAX incluido).' - http://en.cppreference.com/w/cpp/numeric/random/rand

Debes usar RAND_MAX + 1 (es como generar un número dígito por dígito y luego convertirlo a base 10) en lugar de RAND_MAX. esta manera se puede generar números con uno, dos, tres, etc. dígitos en la base RAND_MAX + 1 (posiblemente con ceros a la izquierda) y convertirlos a la base 10 y obtener arbitrariamente grandes números.

Todo lo que obtenga más grande que su MAX_VALUE deseado puede descartarse y usted todavía obtiene 1/(MAX_VALOR + 1) probabilidad de obtener cada número.

Tenga en cuenta que este método puede tardar un tiempo, especialmente si su MAX_VALUE deseado es mucho menor que el valor máximo que se puede obtener antes de descartar los números que no se desean, como el número esperado de pasos para obtener un número en [0, MAX_VALUE] con este algoritmo es: (MAX_OBTAINABLE_VALUE + 1)/(MAX_VALUE + 1)

Cuestiones relacionadas