Generador de números aleatorios comunes de iOS y Android
Necesito un generador de números aleatorios que produce la misma secuencia de números tanto en iOS como en Android si damos la misma semilla en ambos.
Intenté la función de rand () con el srand (1000). Pero dio resultados diferentes. Entonces intenté mersenne twister. Pero eso también dio la secuencia de la diferencia para la misma semilla.
- Gradientes lineales que no funcionan en navegadores web móviles
- Android no puede reproducir vídeo H264 / AAC
- Córdoba: ¿Cómo establecer diferentes nombres de paquetes por plataforma usando el cordova-cli?
- ¿Cómo tener un gradiente transparente sobre una imagen en React iOS nativo?
- Problema Eliminación de una clase / columna de Parse
¿Podría alguien por favor ayudarme en esto.
Estoy utilizando cocos2d-x para mi desarrollo.
- Google Cloud Messaging muestra "notRegistered" al usar la aplicación distribuida de iOS
- IOS - Swift - Devolución de llamada cuando el teléfono se conecta
- Cordova: ¿Cómo configurar el archivo config.xml específico de la plataforma que no se sobrescribe después de construir cordova?
- Envía un enlace al grupo de whatsapp directamente desde el navegador (o desde la aplicación)
- Problema de rotación de imagen de PhoneGap después de la transformación
- Mensaje de varias plataformas a través de AWS SNS con aws-ruby-sdk
- ¿Es posible crear una biblioteca compartida multiplataforma con MonoDroid y MonoTouch que pueden ser utilizados por desarrolladores que no sean Mono?
- Phonegap, textarea no aceptará entrada
He adaptado una biblioteca en línea de CRandomMersenne y lo siento realmente no puedo encontrar la fuente para ése. Pero aquí está mi implementación Mersenne Twister:
// Define 32 bit signed and unsigned integers. // Change these definitions, if necessary, to match a particular platform #if defined(_WIN16) || defined(__MSDOS__) || defined(_MSDOS) // 16 bit systems use long int for 32 bit integer typedef long int int32; // 32 bit signed integer typedef unsigned long int uint32; // 32 bit unsigned integer #else // Most other systems use int for 32 bit integer typedef int int32; // 32 bit signed integer typedef unsigned int uint32; // 32 bit unsigned integer #endif // Define 64 bit signed and unsigned integers, if possible #if (defined(__WINDOWS__) || defined(_WIN32)) && (defined(_MSC_VER) || defined(__INTEL_COMPILER)) // Microsoft and other compilers under Windows use __int64 typedef __int64 int64; // 64 bit signed integer typedef unsigned __int64 uint64; // 64 bit unsigned integer #define INT64_DEFINED // Remember that int64 is defined #elif defined(__unix__) && (defined(_M_IX86) || defined(_M_X64)) // Gnu and other compilers under Linux etc. use long long typedef long long int64; // 64 bit signed integer typedef unsigned long long uint64; // 64 bit unsigned integer #define INT64_DEFINED // Remember that int64 is defined #else // 64 bit integers not defined // You may include definitions for other platforms here #endif void EndOfProgram(void); // System-specific exit code (userintf.cpp) void FatalError(char * ErrorText); // System-specific error reporting (userintf.cpp) class CRandomMersenne { // Encapsulate random number generator #if 0 // Define constants for type MT11213A: #define MERS_N 351 #define MERS_M 175 #define MERS_R 19 #define MERS_U 11 #define MERS_S 7 #define MERS_T 15 #define MERS_L 17 #define MERS_A 0xE4BD75F5 #define MERS_B 0x655E5280 #define MERS_C 0xFFD58000 #else // or constants for type MT19937: #define MERS_N 624 #define MERS_M 397 #define MERS_R 31 #define MERS_U 11 #define MERS_S 7 #define MERS_T 15 #define MERS_L 18 #define MERS_A 0x9908B0DF #define MERS_B 0x9D2C5680 #define MERS_C 0xEFC60000 #endif public: CRandomMersenne(uint32 seed) { // Constructor RandomInit(seed); LastInterval = 0;} void RandomInit(uint32 seed); // Re-seed void RandomInitByArray(uint32 seeds[], int length); // Seed by more than 32 bits int IRandom (int min, int max); // Output random integer int IRandomX(int min, int max); // Output random integer, exact double Random(); // Output random float uint32 BRandom(); // Output random bits private: void Init0(uint32 seed); // Basic initialization procedure uint32 mt[MERS_N]; // State vector int mti; // Index into mt uint32 LastInterval; // Last interval length for IRandomX uint32 RLimit; // Rejection limit used by IRandomX enum TArch {LITTLE_ENDIAN1, BIG_ENDIAN1, NONIEEE}; // Definition of architecture TArch Architecture; // Conversion to float depends on architecture }; class CRandomMother { // Encapsulate random number generator public: void RandomInit(uint32 seed); // Initialization int IRandom(int min, int max); // Get integer random number in desired interval double Random(); // Get floating point random number uint32 BRandom(); // Output random bits CRandomMother(uint32 seed) { // Constructor RandomInit(seed);} protected: uint32 x[5]; // History buffer }; #endif void CRandomMersenne::Init0(uint32 seed) { // Detect computer architecture union {double f; uint32 i[2];} convert; convert.f = 1.0; if (convert.i[1] == 0x3FF00000) Architecture = LITTLE_ENDIAN1; else if (convert.i[0] == 0x3FF00000) Architecture = BIG_ENDIAN1; else Architecture = NONIEEE; // Seed generator mt[0]= seed; for (mti=1; mti < MERS_N; mti++) { mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); } } void CRandomMersenne::RandomInit(uint32 seed) { // Initialize and seed Init0(seed); // Randomize some more for (int i = 0; i < 37; i++) BRandom(); } void CRandomMersenne::RandomInitByArray(uint32 seeds[], int length) { // Seed by more than 32 bits int i, j, k; // Initialize Init0(19650218); if (length <= 0) return; // Randomize mt[] using whole seeds[] array i = 1; j = 0; k = (MERS_N > length ? MERS_N : length); for (; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + seeds[j] + j; i++; j++; if (i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;} if (j >= length) j=0;} for (k = MERS_N-1; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i; if (++i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}} mt[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array // Randomize some more mti = 0; for (int i = 0; i <= MERS_N; i++) BRandom(); } uint32 CRandomMersenne::BRandom() { // Generate 32 random bits uint32 y; if (mti >= MERS_N) { // Generate MERS_N words at one time const uint32 LOWER_MASK = (1LU << MERS_R) - 1; // Lower MERS_R bits const uint32 UPPER_MASK = 0xFFFFFFFF << MERS_R; // Upper (32 - MERS_R) bits static const uint32 mag01[2] = {0, MERS_A}; int kk; for (kk=0; kk < MERS_N-MERS_M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+MERS_M] ^ (y >> 1) ^ mag01[y & 1];} for (; kk < MERS_N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(MERS_M-MERS_N)] ^ (y >> 1) ^ mag01[y & 1];} y = (mt[MERS_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[MERS_N-1] = mt[MERS_M-1] ^ (y >> 1) ^ mag01[y & 1]; mti = 0; } y = mt[mti++]; #if 1 // Tempering (May be omitted): y ^= y >> MERS_U; y ^= (y << MERS_S) & MERS_B; y ^= (y << MERS_T) & MERS_C; y ^= y >> MERS_L; #endif return y; } double CRandomMersenne::Random() { // Output random float number in the interval 0 <= x < 1 union {double f; uint32 i[2];} convert; uint32 r = BRandom(); // Get 32 random bits // The fastest way to convert random bits to floating point is as follows: // Set the binary exponent of a floating point number to 1+bias and set // the mantissa to random bits. This will give a random number in the // interval [1,2). Then subtract 1.0 to get a random number in the interval // [0,1). This procedure requires that we know how floating point numbers // are stored. The storing method is tested in function RandomInit and saved // in the variable Architecture. // This shortcut allows the compiler to optimize away the following switch // statement for the most common architectures: #if defined(_M_IX86) || defined(_M_X64) || defined(__LITTLE_ENDIAN__) Architecture = LITTLE_ENDIAN1; #elif defined(__BIG_ENDIAN__) Architecture = BIG_ENDIAN1; #endif switch (Architecture) { case LITTLE_ENDIAN1: convert.i[0] = r << 20; convert.i[1] = (r >> 12) | 0x3FF00000; return convert.f - 1.0; case BIG_ENDIAN1: convert.i[1] = r << 20; convert.i[0] = (r >> 12) | 0x3FF00000; return convert.f - 1.0; case NONIEEE: default: ; } // This somewhat slower method works for all architectures, including // non-IEEE floating point representation: return (double)r * (1./((double)(uint32)(-1L)+1.)); } int CRandomMersenne::IRandom(int min, int max) { // Output random integer in the interval min <= x <= max // Relative error on frequencies < 2^-32 if (max <= min) { if (max == min) return min; else return 0x80000000; } // Multiply interval with random and truncate int r = int((max - min + 1) * Random()) + min; if (r > max) r = max; return r; } int CRandomMersenne::IRandomX(int min, int max) { // Output random integer in the interval min <= x <= max // Each output value has exactly the same probability. // This is obtained by rejecting certain bit values so that the number // of possible bit values is divisible by the interval length if (max <= min) { if (max == min) return min; else return 0x80000000; } #ifdef INT64_DEFINED // 64 bit integers available. Use multiply and shift method uint32 interval; // Length of interval uint64 longran; // Random bits * interval uint32 iran; // Longran / 2^32 uint32 remainder; // Longran % 2^32 interval = uint32(max - min + 1); if (interval != LastInterval) { // Interval length has changed. Must calculate rejection limit // Reject when remainder = 2^32 / interval * interval // RLimit will be 0 if interval is a power of 2. No rejection then RLimit = uint32(((uint64)1 << 32) / interval) * interval - 1; LastInterval = interval; } do { // Rejection loop longran = (uint64)BRandom() * interval; iran = (uint32)(longran >> 32); remainder = (uint32)longran; } while (remainder > RLimit); // Convert back to signed and return result return (int32)iran + min; #else // 64 bit integers not available. Use modulo method uint32 interval; // Length of interval uint32 bran; // Random bits uint32 iran; // bran / interval uint32 remainder; // bran % interval interval = uint32(max - min + 1); if (interval != LastInterval) { // Interval length has changed. Must calculate rejection limit // Reject when iran = 2^32 / interval // We can't make 2^32 so we use 2^32-1 and correct afterwards RLimit = (uint32)0xFFFFFFFF / interval; if ((uint32)0xFFFFFFFF % interval == interval - 1) RLimit++; } do { // Rejection loop bran = BRandom(); iran = bran / interval; remainder = bran % interval; } while (iran >= RLimit); // Convert back to signed and return result return (int32)remainder + min; #endif }
El uso de la clase anterior es bastante simple:
CRandomMersenne generator(<some_seed>); generator.random(); // random value [0,1] generator.IRandom(a,b); // random value [a,b]
He probado esto muchas veces y funciona mejor y más rápidamente que la mayoría de los generadores aleatorios del número que he visto.
Muchas veces me he basado en el hecho de que es determinista dado una semilla para que pueda usarlo, supongo. Voy a tratar de encontrar la fuente original para ese código y dar el crédito al autor.
EDIT: el autor del código de arriba es Agner Fog y en su sitio web hay una sección completa para generadores de números aleatorios. Todo el crédito por el código va a él.
Sólo puede escribir su propio generador de números aleatorios como este. La calidad es baja, pero se adapte a la mayor parte del propósito.
// RAND_MAX assumed to be 32767. static unsigned long int next = 1; void srand(unsigned int seed) { next = seed; } int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % 32768; }
puedes usar:
#import <stdlib.h> int randomNumber = arc4random() % limiteNumber;