Why would rand() return a negative value when min and max values are positive?

后端 未结 2 1930
南笙
南笙 2020-12-20 01:34

I have a simple piece of PHP code which requires a random number to be created. However, even though the input is always positive, it sometimes returns a negative output.

相关标签:
2条回答
  • 2020-12-20 01:49

    Rand takes as arguments, and returns, integers. Integers (in PHP) usually have a maximum range of 2**32.

    Your double arguments are larger than this, causing an integer overflow when they are converted to integers.

    0 讨论(0)
  • 2020-12-20 01:57

    Because you're seeing an integer overflow in the arguments.

    According to the rand() documentation it takes two int values as arguments. On a 32-bit machine those are 32 bit as well (at least for PHP). So when you pass arguments larger than 231 − 1 they overflow and start at −231 again.

    Apparently, if you need larger values you'll have to code it yourself. While simply creating a 64-bit number from two 32-bit numbers works as intended, you can't simply do a modulo operation with your maximum value since that skews the distribution. For a good implementation how to generate a uniformly-distributed random integer between 0 and a certain upper bound you can take a look at java.util.Random.nextInt(int) and adapt accordingly for 64 bit integers.

    mt_rand() while usually a nice choice for random numbers because it uses MT19937 instead of a poor LCG, doesn't help here either as its arguments are ints as well.


    Another option you might want to consider if you don't require every possible value to be picked eventually:

    • Generate a random floating-point value between 0 and 1 by calling

      $rnd = mt_rand() / (double)mt_getrandmax()
      
    • Determine the range of numbers you need:

      $min = $this->gdp * 0.02;
      $max = $this->gdp * 0.17;
      $range = $max - $min;
      
    • Multiply this by the previously-obtained random floating-point value and add the minimum:

      $value = $min + $range * $rnd
      
    • Now you have a random value between your chosen boundaries. It's approximately uniformly distributed, although there are discrete steps between adjacent random numbers as you are stretching 32 bits of randomness over a larger number of bits. If that's no problem for you, go ahead, though.

    0 讨论(0)
提交回复
热议问题