Почему rand () возвращает отрицательное значение, когда значения min и max являются положительными?

У меня есть простой фрагмент кода PHP, который требует создания произвольного числа. Однако, хотя вход всегда положительный, он иногда возвращает отрицательный результат.

Вот мой код отладки:

$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() из двух положительных чисел дает отрицательный доход?

Любая помощь приветствуется!

Solutions Collecting From Web of "Почему rand () возвращает отрицательное значение, когда значения min и max являются положительными?"

Потому что вы видите переполнение целых чисел в аргументах.

Согласно документации rand () в качестве аргументов требуется два значения int . На 32-битной машине тоже 32 бита (по крайней мере для PHP). Поэтому, когда вы передаете аргументы, превышающие 2 31 – 1, они переполняются и начинаются с -2 31 снова.

По-видимому, если вам нужны более высокие значения, вам придется самому закодировать их. Хотя простое создание 64-битного номера из двух 32-разрядных чисел работает по назначению, вы не можете просто выполнять операцию по модулю с максимальным значением, так как это перекосит дистрибутив. Для хорошей реализации, как создать равномерно распределенное случайное целое число от 0 до некоторой верхней границы, вы можете взглянуть на java.util.Random.nextInt (int) и соответственно адаптировать для 64-битных целых чисел.

mt_rand (), хотя обычно хороший выбор для случайных чисел, потому что он использует MT19937 вместо плохого LCG, здесь не помогает, поскольку его аргументы также являются int s.


Другой вариант, который вы, возможно, захотите рассмотреть, если в конечном итоге не будет выбрано все возможные значения:

  • Создайте случайное значение с плавающей запятой между 0 и 1, вызвав

     $rnd = mt_rand() / (double)mt_getrandmax() 
  • Определите диапазон нужных номеров:

     $min = $this->gdp * 0.02; $max = $this->gdp * 0.17; $range = $max - $min; 
  • Умножьте это на ранее полученное случайное значение с плавающей запятой и добавьте минимум:

     $value = $min + $range * $rnd 
  • Теперь у вас есть случайное значение между выбранными вами границами. Он приблизительно равномерно распределен, хотя между соседними случайными числами существуют дискретные шаги, так как вы растягиваете 32 бита случайности по сравнению с большим количеством бит. Если это не проблема для вас, продолжайте.

Rand принимает в качестве аргументов и возвращает целые числа . Целые числа (в PHP) обычно имеют максимальный диапазон 2 ** 32.

Ваши двойные аргументы больше этого, вызывая переполнение целых чисел, когда они преобразуются в целые числа.