iOS和Android的常用随机数生成器

前端之家收集整理的这篇文章主要介绍了iOS和Android的常用随机数生成器前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如果我们在两者中都提供相同的种子,我需要一个在iOS和 Android中产生相同数字序列的随机生成器.

我用srand(1000)尝试了rand()函数.但它给出了不同的输出.
然后我尝试了mersenne twister.但这也为同一种子提供了不同的序列.

有谁可以帮我这个.

我正在使用cocos2d-x进行开发.

解决方法

我已经改编了一个在线CRandomMersenne库,我真的很抱歉,我再也找不到那个来源了.但这是我的Mersenne Twister实施:
  1. // Define 32 bit signed and unsigned integers.
  2. // Change these definitions,if necessary,to match a particular platform
  3. #if defined(_WIN16) || defined(__MSDOS__) || defined(_MSDOS)
  4. // 16 bit systems use long int for 32 bit integer
  5. typedef long int int32; // 32 bit signed integer
  6. typedef unsigned long int uint32; // 32 bit unsigned integer
  7. #else
  8. // Most other systems use int for 32 bit integer
  9. typedef int int32; // 32 bit signed integer
  10. typedef unsigned int uint32; // 32 bit unsigned integer
  11. #endif
  12.  
  13. // Define 64 bit signed and unsigned integers,if possible
  14. #if (defined(__WINDOWS__) || defined(_WIN32)) && (defined(_MSC_VER) || defined(__INTEL_COMPILER))
  15. // Microsoft and other compilers under Windows use __int64
  16. typedef __int64 int64; // 64 bit signed integer
  17. typedef unsigned __int64 uint64; // 64 bit unsigned integer
  18. #define INT64_DEFINED // Remember that int64 is defined
  19. #elif defined(__unix__) && (defined(_M_IX86) || defined(_M_X64))
  20. // Gnu and other compilers under Linux etc. use long long
  21. typedef long long int64; // 64 bit signed integer
  22. typedef unsigned long long uint64; // 64 bit unsigned integer
  23. #define INT64_DEFINED // Remember that int64 is defined
  24. #else
  25. // 64 bit integers not defined
  26. // You may include definitions for other platforms here
  27. #endif
  28.  
  29. void EndOfProgram(void); // System-specific exit code (userintf.cpp)
  30.  
  31. void FatalError(char * ErrorText); // System-specific error reporting (userintf.cpp)
  32.  
  33. class CRandomMersenne { // Encapsulate random number generator
  34. #if 0
  35. // Define constants for type MT11213A:
  36. #define MERS_N 351
  37. #define MERS_M 175
  38. #define MERS_R 19
  39. #define MERS_U 11
  40. #define MERS_S 7
  41. #define MERS_T 15
  42. #define MERS_L 17
  43. #define MERS_A 0xE4BD75F5
  44. #define MERS_B 0x655E5280
  45. #define MERS_C 0xFFD58000
  46. #else
  47. // or constants for type MT19937:
  48. #define MERS_N 624
  49. #define MERS_M 397
  50. #define MERS_R 31
  51. #define MERS_U 11
  52. #define MERS_S 7
  53. #define MERS_T 15
  54. #define MERS_L 18
  55. #define MERS_A 0x9908B0DF
  56. #define MERS_B 0x9D2C5680
  57. #define MERS_C 0xEFC60000
  58. #endif
  59. public:
  60. CRandomMersenne(uint32 seed) { // Constructor
  61. RandomInit(seed); LastInterval = 0;}
  62. void RandomInit(uint32 seed); // Re-seed
  63. void RandomInitByArray(uint32 seeds[],int length); // Seed by more than 32 bits
  64. int IRandom (int min,int max); // Output random integer
  65. int IRandomX(int min,int max); // Output random integer,exact
  66. double Random(); // Output random float
  67. uint32 BRandom(); // Output random bits
  68. private:
  69. void Init0(uint32 seed); // Basic initialization procedure
  70. uint32 mt[MERS_N]; // State vector
  71. int mti; // Index into mt
  72. uint32 LastInterval; // Last interval length for IRandomX
  73. uint32 RLimit; // Rejection limit used by IRandomX
  74. enum TArch {LITTLE_ENDIAN1,BIG_ENDIAN1,NONIEEE}; // Definition of architecture
  75. TArch Architecture; // Conversion to float depends on architecture
  76. };
  77.  
  78.  
  79. class CRandomMother { // Encapsulate random number generator
  80. public:
  81. void RandomInit(uint32 seed); // Initialization
  82. int IRandom(int min,int max); // Get integer random number in desired interval
  83. double Random(); // Get floating point random number
  84. uint32 BRandom(); // Output random bits
  85. CRandomMother(uint32 seed) { // Constructor
  86. RandomInit(seed);}
  87. protected:
  88. uint32 x[5]; // History buffer
  89. };
  90.  
  91. #endif
  92.  
  93. void CRandomMersenne::Init0(uint32 seed) {
  94. // Detect computer architecture
  95. union {double f; uint32 i[2];} convert;
  96. convert.f = 1.0;
  97. if (convert.i[1] == 0x3FF00000) Architecture = LITTLE_ENDIAN1;
  98. else if (convert.i[0] == 0x3FF00000) Architecture = BIG_ENDIAN1;
  99. else Architecture = NONIEEE;
  100.  
  101. // Seed generator
  102. mt[0]= seed;
  103. for (mti=1; mti < MERS_N; mti++) {
  104. mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
  105. }
  106. }
  107.  
  108. void CRandomMersenne::RandomInit(uint32 seed) {
  109. // Initialize and seed
  110. Init0(seed);
  111.  
  112. // Randomize some more
  113. for (int i = 0; i < 37; i++) BRandom();
  114. }
  115.  
  116.  
  117. void CRandomMersenne::RandomInitByArray(uint32 seeds[],int length) {
  118. // Seed by more than 32 bits
  119. int i,j,k;
  120.  
  121. // Initialize
  122. Init0(19650218);
  123.  
  124. if (length <= 0) return;
  125.  
  126. // Randomize mt[] using whole seeds[] array
  127. i = 1; j = 0;
  128. k = (MERS_N > length ? MERS_N : length);
  129. for (; k; k--) {
  130. mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + seeds[j] + j;
  131. i++; j++;
  132. if (i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}
  133. if (j >= length) j=0;}
  134. for (k = MERS_N-1; k; k--) {
  135. mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i;
  136. if (++i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}}
  137. mt[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array
  138.  
  139. // Randomize some more
  140. mti = 0;
  141. for (int i = 0; i <= MERS_N; i++) BRandom();
  142. }
  143.  
  144.  
  145. uint32 CRandomMersenne::BRandom() {
  146. // Generate 32 random bits
  147. uint32 y;
  148.  
  149. if (mti >= MERS_N) {
  150. // Generate MERS_N words at one time
  151. const uint32 LOWER_MASK = (1LU << MERS_R) - 1; // Lower MERS_R bits
  152. const uint32 UPPER_MASK = 0xFFFFFFFF << MERS_R; // Upper (32 - MERS_R) bits
  153. static const uint32 mag01[2] = {0,MERS_A};
  154.  
  155. int kk;
  156. for (kk=0; kk < MERS_N-MERS_M; kk++) {
  157. y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
  158. mt[kk] = mt[kk+MERS_M] ^ (y >> 1) ^ mag01[y & 1];}
  159.  
  160. for (; kk < MERS_N-1; kk++) {
  161. y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
  162. mt[kk] = mt[kk+(MERS_M-MERS_N)] ^ (y >> 1) ^ mag01[y & 1];}
  163.  
  164. y = (mt[MERS_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
  165. mt[MERS_N-1] = mt[MERS_M-1] ^ (y >> 1) ^ mag01[y & 1];
  166. mti = 0;
  167. }
  168.  
  169. y = mt[mti++];
  170.  
  171. #if 1
  172. // Tempering (May be omitted):
  173. y ^= y >> MERS_U;
  174. y ^= (y << MERS_S) & MERS_B;
  175. y ^= (y << MERS_T) & MERS_C;
  176. y ^= y >> MERS_L;
  177. #endif
  178.  
  179. return y;
  180. }
  181.  
  182.  
  183. double CRandomMersenne::Random() {
  184. // Output random float number in the interval 0 <= x < 1
  185. union {double f; uint32 i[2];} convert;
  186. uint32 r = BRandom(); // Get 32 random bits
  187. // The fastest way to convert random bits to floating point is as follows:
  188. // Set the binary exponent of a floating point number to 1+bias and set
  189. // the mantissa to random bits. This will give a random number in the
  190. // interval [1,2). Then subtract 1.0 to get a random number in the interval
  191. // [0,1). This procedure requires that we know how floating point numbers
  192. // are stored. The storing method is tested in function RandomInit and saved
  193. // in the variable Architecture.
  194.  
  195. // This shortcut allows the compiler to optimize away the following switch
  196. // statement for the most common architectures:
  197. #if defined(_M_IX86) || defined(_M_X64) || defined(__LITTLE_ENDIAN__)
  198. Architecture = LITTLE_ENDIAN1;
  199. #elif defined(__BIG_ENDIAN__)
  200. Architecture = BIG_ENDIAN1;
  201. #endif
  202.  
  203. switch (Architecture) {
  204. case LITTLE_ENDIAN1:
  205. convert.i[0] = r << 20;
  206. convert.i[1] = (r >> 12) | 0x3FF00000;
  207. return convert.f - 1.0;
  208. case BIG_ENDIAN1:
  209. convert.i[1] = r << 20;
  210. convert.i[0] = (r >> 12) | 0x3FF00000;
  211. return convert.f - 1.0;
  212. case NONIEEE: default: ;
  213. }
  214. // This somewhat slower method works for all architectures,including
  215. // non-IEEE floating point representation:
  216. return (double)r * (1./((double)(uint32)(-1L)+1.));
  217. }
  218.  
  219.  
  220. int CRandomMersenne::IRandom(int min,int max) {
  221. // Output random integer in the interval min <= x <= max
  222. // Relative error on frequencies < 2^-32
  223. if (max <= min) {
  224. if (max == min) return min; else return 0x80000000;
  225. }
  226. // Multiply interval with random and truncate
  227. int r = int((max - min + 1) * Random()) + min;
  228. if (r > max) r = max;
  229. return r;
  230. }
  231.  
  232.  
  233. int CRandomMersenne::IRandomX(int min,int max) {
  234. // Output random integer in the interval min <= x <= max
  235. // Each output value has exactly the same probability.
  236. // This is obtained by rejecting certain bit values so that the number
  237. // of possible bit values is divisible by the interval length
  238. if (max <= min) {
  239. if (max == min) return min; else return 0x80000000;
  240. }
  241. #ifdef INT64_DEFINED
  242. // 64 bit integers available. Use multiply and shift method
  243. uint32 interval; // Length of interval
  244. uint64 longran; // Random bits * interval
  245. uint32 iran; // Longran / 2^32
  246. uint32 remainder; // Longran % 2^32
  247.  
  248. interval = uint32(max - min + 1);
  249. if (interval != LastInterval) {
  250. // Interval length has changed. Must calculate rejection limit
  251. // Reject when remainder = 2^32 / interval * interval
  252. // RLimit will be 0 if interval is a power of 2. No rejection then
  253. RLimit = uint32(((uint64)1 << 32) / interval) * interval - 1;
  254. LastInterval = interval;
  255. }
  256. do { // Rejection loop
  257. longran = (uint64)BRandom() * interval;
  258. iran = (uint32)(longran >> 32);
  259. remainder = (uint32)longran;
  260. } while (remainder > RLimit);
  261. // Convert back to signed and return result
  262. return (int32)iran + min;
  263.  
  264. #else
  265. // 64 bit integers not available. Use modulo method
  266. uint32 interval; // Length of interval
  267. uint32 bran; // Random bits
  268. uint32 iran; // bran / interval
  269. uint32 remainder; // bran % interval
  270.  
  271. interval = uint32(max - min + 1);
  272. if (interval != LastInterval) {
  273. // Interval length has changed. Must calculate rejection limit
  274. // Reject when iran = 2^32 / interval
  275. // We can't make 2^32 so we use 2^32-1 and correct afterwards
  276. RLimit = (uint32)0xFFFFFFFF / interval;
  277. if ((uint32)0xFFFFFFFF % interval == interval - 1) RLimit++;
  278. }
  279. do { // Rejection loop
  280. bran = BRandom();
  281. iran = bran / interval;
  282. remainder = bran % interval;
  283. } while (iran >= RLimit);
  284. // Convert back to signed and return result
  285. return (int32)remainder + min;
  286.  
  287. #endif
  288. }

上面这个类的用法很简单:

  1. CRandomMersenne generator(<some_seed>);
  2. generator.random(); // random value [0,1]
  3. generator.IRandom(a,b); // random value [a,b]

我已经测试了很多次,它比我见过的大多数随机数发生器表现得更好更快.

很多时候,我依赖于这样一个事实:给定种子是确定性的,所以你可以使用它.我将尝试找到该代码的原始来源并将其归功于作者.

编辑:上面代码的作者是Agner Fog,在他的网站上有一个完整的section随机生成器.代码的所有功劳归于他.

猜你在找的iOS相关文章