返回介绍

random_int()

发布于 2017-09-11 10:03:23 字数 5332 浏览 1104 评论 0 收藏 0

random_int( int $min,  int $max )

Fetch a random integer between $min and $max inclusive


description


参数

$min

(int) (Required)

$max

(int) (Required)


返回值

(int)


源代码

File: wp-includes/random_compat/random_int.php

function random_int($min, $max)
{
    /**
     * Type and input logic checks
     * 
     * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
     * (non-inclusive), it will sanely cast it to an int. If you it's equal to
     * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats 
     * lose precision, so the <= and => operators might accidentally let a float
     * through.
     */
    
    try {
        $min = RandomCompat_intval($min);
    } catch (TypeError $ex) {
        throw new TypeError(
            'random_int(): $min must be an integer'
        );
    }

    try {
        $max = RandomCompat_intval($max);
    } catch (TypeError $ex) {
        throw new TypeError(
            'random_int(): $max must be an integer'
        );
    }
    
    /**
     * Now that we've verified our weak typing system has given us an integer,
     * let's validate the logic then we can move forward with generating random
     * integers along a given range.
     */
    if ($min > $max) {
        throw new Error(
            'Minimum value must be less than or equal to the maximum value'
        );
    }

    if ($max === $min) {
        return $min;
    }

    /**
     * Initialize variables to 0
     * 
     * We want to store:
     * $bytes => the number of random bytes we need
     * $mask => an integer bitmask (for use with the &) operator
     *          so we can minimize the number of discards
     */
    $attempts = $bits = $bytes = $mask = $valueShift = 0;

    /**
     * At this point, $range is a positive number greater than 0. It might
     * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
     * a float and we will lose some precision.
     */
    $range = $max - $min;

    /**
     * Test for integer overflow:
     */
    if (!is_int($range)) {

        /**
         * Still safely calculate wider ranges.
         * Provided by @CodesInChaos, @oittaa
         * 
         * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
         * 
         * We use ~0 as a mask in this case because it generates all 1s
         * 
         * @ref https://eval.in/400356 (32-bit)
         * @ref http://3v4l.org/XX9r5  (64-bit)
         */
        $bytes = PHP_INT_SIZE;
        $mask = ~0;

    } else {

        /**
         * $bits is effectively ceil(log($range, 2)) without dealing with 
         * type juggling
         */
        while ($range > 0) {
            if ($bits % 8 === 0) {
               ++$bytes;
            }
            ++$bits;
            $range >>= 1;
            $mask = $mask << 1 | 1;
        }
        $valueShift = $min;
    }

    /**
     * Now that we have our parameters set up, let's begin generating
     * random integers until one falls between $min and $max
     */
    do {
        /**
         * The rejection probability is at most 0.5, so this corresponds
         * to a failure probability of 2^-128 for a working RNG
         */
        if ($attempts > 128) {
            throw new Exception(
                'random_int: RNG is broken - too many rejections'
            );
        }

        /**
         * Let's grab the necessary number of random bytes
         */
        $randomByteString = random_bytes($bytes);
        if ($randomByteString === false) {
            throw new Exception(
                'Random number generator failure'
            );
        }

        /**
         * Let's turn $randomByteString into an integer
         * 
         * This uses bitwise operators (<< and |) to build an integer
         * out of the values extracted from ord()
         * 
         * Example: [9F] | [6D] | [32] | [0C] =>
         *   159 + 27904 + 3276800 + 201326592 =>
         *   204631455
         */
        $val = 0;
        for ($i = 0; $i < $bytes; ++$i) {
            $val |= ord($randomByteString[$i]) << ($i * 8);
        }

        /**
         * Apply mask
         */
        $val &= $mask;
        $val += $valueShift;

        ++$attempts;
        /**
         * If $val overflows to a floating point number,
         * ... or is larger than $max,
         * ... or smaller than $min,
         * then try again.
         */
    } while (!is_int($val) || $val > $max || $val < $min);

    return (int) $val;
}

Collapse full 源代码 code View on Trac


相关函数

Uses

  • wp-includes/random_compat/cast_to_int.php: RandomCompat_intval()
  • wp-includes/random_compat/random_bytes_dev_urandom.php: random_bytes()

Used By

  • wp-includes/pluggable.php: wp_rand()

User Contributed Notes

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文