random_int

Fetch a random integer between $min and $max inclusive.

Description

(int) random_int( (int) $min, (int) $max ); 

Returns (int)

Parameters (2)

0. $min (int)
The min.
1. $max (int)
The max.

Usage

  1. if ( !function_exists( 'random_int' ) ) { 
  2. require_once ABSPATH . WPINC . '/random_compat/random_int.php'; 
  3.  
  4. // The min. 
  5. $min = -1; 
  6.  
  7. // The max. 
  8. $max = -1; 
  9.  
  10. // NOTICE! Understand what this does before running. 
  11. $result = random_int($min, $max); 
  12.  

Defined (1)

The function is defined in the following location(s).

/wp-includes/random_compat/random_int.php  
  1. function random_int($min, $max) 
  2. /** 
  3. * Type and input logic checks 
  4. *  
  5. * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX) 
  6. * (non-inclusive), it will sanely cast it to an int. If you it's equal to 
  7. * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats  
  8. * lose precision, so the <= and => operators might accidentally let a float 
  9. * through. 
  10. */ 
  11.  
  12. try { 
  13. $min = RandomCompat_intval($min); 
  14. } catch (TypeError $ex) { 
  15. throw new TypeError
  16. 'random_int(): $min must be an integer' 
  17. ); 
  18.  
  19. try { 
  20. $max = RandomCompat_intval($max); 
  21. } catch (TypeError $ex) { 
  22. throw new TypeError
  23. 'random_int(): $max must be an integer' 
  24. ); 
  25.  
  26. /** 
  27. * Now that we've verified our weak typing system has given us an integer,  
  28. * let's validate the logic then we can move forward with generating random 
  29. * integers along a given range. 
  30. */ 
  31. if ($min > $max) { 
  32. throw new Error
  33. 'Minimum value must be less than or equal to the maximum value' 
  34. ); 
  35.  
  36. if ($max === $min) { 
  37. return $min; 
  38.  
  39. /** 
  40. * Initialize variables to 0 
  41. *  
  42. * We want to store: 
  43. * $bytes => the number of random bytes we need 
  44. * $mask => an integer bitmask (for use with the &) operator 
  45. * so we can minimize the number of discards 
  46. */ 
  47. $attempts = $bits = $bytes = $mask = $valueShift = 0; 
  48.  
  49. /** 
  50. * At this point, $range is a positive number greater than 0. It might 
  51. * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to 
  52. * a float and we will lose some precision. 
  53. */ 
  54. $range = $max - $min; 
  55.  
  56. /** 
  57. * Test for integer overflow: 
  58. */ 
  59. if (!is_int($range)) { 
  60.  
  61. /** 
  62. * Still safely calculate wider ranges. 
  63. * Provided by @CodesInChaos, @oittaa 
  64. *  
  65. * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 
  66. *  
  67. * We use ~0 as a mask in this case because it generates all 1s 
  68. *  
  69. * @ref https://eval.in/400356 (32-bit) 
  70. * @ref http://3v4l.org/XX9r5 (64-bit) 
  71. */ 
  72. $bytes = PHP_INT_SIZE; 
  73. $mask = ~0; 
  74.  
  75. } else { 
  76.  
  77. /** 
  78. * $bits is effectively ceil(log($range, 2)) without dealing with  
  79. * type juggling 
  80. */ 
  81. while ($range > 0) { 
  82. if ($bits % 8 === 0) { 
  83. ++$bytes; 
  84. ++$bits; 
  85. $range >>= 1; 
  86. $mask = $mask << 1 | 1; 
  87. $valueShift = $min; 
  88.  
  89. /** 
  90. * Now that we have our parameters set up, let's begin generating 
  91. * random integers until one falls between $min and $max 
  92. */ 
  93. do { 
  94. /** 
  95. * The rejection probability is at most 0.5, so this corresponds 
  96. * to a failure probability of 2^-128 for a working RNG 
  97. */ 
  98. if ($attempts > 128) { 
  99. throw new Exception( 
  100. 'random_int: RNG is broken - too many rejections' 
  101. ); 
  102.  
  103. /** 
  104. * Let's grab the necessary number of random bytes 
  105. */ 
  106. $randomByteString = random_bytes($bytes); 
  107. if ($randomByteString === false) { 
  108. throw new Exception( 
  109. 'Random number generator failure' 
  110. ); 
  111.  
  112. /** 
  113. * Let's turn $randomByteString into an integer 
  114. *  
  115. * This uses bitwise operators (<< and |) to build an integer 
  116. * out of the values extracted from ord() 
  117. *  
  118. * Example: [9F] | [6D] | [32] | [0C] => 
  119. * 159 + 27904 + 3276800 + 201326592 => 
  120. * 204631455 
  121. */ 
  122. $val = 0; 
  123. for ($i = 0; $i < $bytes; ++$i) { 
  124. $val |= ord($randomByteString[$i]) << ($i * 8); 
  125.  
  126. /** 
  127. * Apply mask 
  128. */ 
  129. $val &= $mask; 
  130. $val += $valueShift; 
  131.  
  132. ++$attempts; 
  133. /** 
  134. * If $val overflows to a floating point number,  
  135. * ... or is larger than $max,  
  136. * ... or smaller than $min,  
  137. * then try again. 
  138. */ 
  139. } while (!is_int($val) || $val > $max || $val < $min); 
  140.  
  141. return (int) $val;