当最小值和最大值为正数时,为什么rand()返回负数? [英] Why would rand() return a negative value when min and max values are positive?

查看:197
本文介绍了当最小值和最大值为正数时,为什么rand()返回负数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段简单的PHP代码,需要创建一个随机数.但是,即使输入始终为正,有时也会返回负输出.

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.

这是我的调试代码:

$debt = rand($this->gdp * 0.02, $this->gdp * 0.17);
echo "<p>GDP: ".$this->gdp." rand(".$this->gdp * 0.02."  , ".$this->gdp * 0.17.") = <strong>".$debt."</strong></p>";

这是示例输出:

GDP: 219254674605 rand(4385093492.1 , 37273294682.85) = 75276999

GDP: 345015694865 rand(6900313897.3 , 58652668127.05) = -1636353016

GDP: 90445390920 rand(1808907818.4 , 15375716456.4) = -165604705

GDP: 3412849650 rand(68256993 , 580184440.5) = 347516196

GDP: 2939111315 rand(58782226.3 , 499648923.55) = 119181875

GDP: 26369065 rand(527381.3 , 4482741.05) = 3632416

GDP: 215838135 rand(4316762.7 , 36692482.95) = 28784811

GDP: 511763530 rand(10235270.6 , 86999800.1) = 39954394

GDP: 42416245 rand(848324.9 , 7210761.65) = 3974882

GDP: 75090235 rand(1501804.7 , 12765339.95) = 5201966

那么为什么两个正数的rand()会带来负数回报?

So why would a rand() of two positive numbers give a negative return?

任何帮助将不胜感激!

推荐答案

因为您看到参数中出现整数溢出.

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

根据 rand()文档,它使用两个int值作为参数.在32位计算机上,它们也是32位(至少对于PHP).因此,当您传递大于2 31 −的参数时1它们溢出并再次从− 2 31 开始.

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.

显然,如果您需要更大的值,则必须自己编写.从两个32位数字简单地创建一个64位数字可以达到预期的效果,但是您不能简单地使用最大值进行模运算,因为这会使分布产生偏差.为了获得良好的实现效果,如何生成介于0和某个上限之间的均匀分布的随机整数,可以查看

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(),但通常是随机选择的好选择数字,因为它使用MT19937代替了较差的LCG,在这里也无济于事,因为其参数也是int.

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:

  • 通过调用生成介于0和1之间的随机浮点值

  • 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
    

  • 现在,您在所选边界之间有了一个随机值.尽管您将32位的随机性扩展到更多的位上,但是相邻的随机数之间存在离散的步长,因此它的分布大致均匀.如果那对您来说没问题,请继续.

  • 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.

    这篇关于当最小值和最大值为正数时,为什么rand()返回负数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆