php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #60543 mt_rand() only reliable when ($max - $min) <= mt_getrandmax ()
Submitted: 2011-12-16 01:55 UTC Modified: 2015-08-15 10:23 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: daniel at danielnorton dot com Assigned: cmb (profile)
Status: Duplicate Package: Math related
PHP Version: 5.3.8 OS: Windows
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: daniel at danielnorton dot com
New email:
PHP Version: OS:

 

 [2011-12-16 01:55 UTC] daniel at danielnorton dot com
Description:
------------
Example output from the following script that generates 16 random numbers in the 
range from -1073741823 to 2147483647. It shows that the number 1073741825 was 
repeated 4 times, or 25% of the time. This output is typical and the repeated 
number is always 1073741825. The problem is less the smaller the magnitude of 
$min.


Test script:
---------------
<?php

printf("PHP_VERSION=%s\n",PHP_VERSION);
$min = -(mt_getrandmax()>>1);
$max = mt_getrandmax();
$count = isset($argv[1])?(int)$argv[1]:16;
printf("min=%d, max=%d, count=%d\n",$min,$max,$count);

$repeat_counts = array();

for ($i=0;$i<$count;$i++) {
  $random = mt_rand($min,$max);
  if (!isset($repeat_counts[$random])) {
    $repeat_counts[$random] = 0;
  }
  $repeat_counts[$random]++;
  //printf("%12d%s\n", abs($random),($random<0)?"-":"");
}

$max_repeat_count = max($repeat_counts);
$same_value_max = array();
if ($max_repeat_count > 1) {
  foreach ($repeat_counts as $value => $repeat_count) {
    if ($repeat_count >= $max_repeat_count) {
      $same_value_max[] = $value;
    }
  }
  printf("The following number/s was/were repeated %d times (%s%%): %s\n"
    ,$max_repeat_count
    ,number_format(($max_repeat_count/$count)*100.0,1)
    ,implode(", ",$same_value_max)
    );
}


Expected result:
----------------
PHP_VERSION=5.3.8
min=-1073741823, max=2147483647, count=16



Actual result:
--------------
PHP_VERSION=5.3.8
min=-1073741823, max=2147483647, count=16
The following number/s was/were repeated 4 times (25.0%): 1073741825


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-12-16 05:11 UTC] daniel at danielnorton dot com
Further study in a 32-bit environment shows:
**1) The problem does not seem to surface when the absolute value of
both the $min and $max is within 0x3FFFFFFF. In other words, it works
as expected when the range is within -1073807359 ... 1073807359
(-0x3FFFFFFF ... 0x3FFFFFFF).

**2) The oft-repeated value is always $min & 0x7FFFFFFF, which is
always a positive integer.
 [2011-12-16 05:38 UTC] daniel at danielnorton dot com
In a 64-bit environment, although documented to be limited to
mt_getrandmax() (which is 0x7FFFFFFF in my environment), for
the purposes of diagnosis, the following is notable:

**1) The problem does not seem to surface when the absolute value
of both the $min and $max is within (PHP_INT_MAX/2)-1
(0x3FFFFFFFFFFFFFFF).

**2) The oft-repeated value is always $min & PHP_INT_MAX, which
always yields a positive integer.
 [2011-12-16 06:18 UTC] daniel at danielnorton dot com
The problem does not appear if ($max - $min) <= PHP_INT_MAX.

Perhaps this is a documentation problem and the solution might simply be to 
specify that ($max - $min) must be less than mt_getrandmax()?
 [2011-12-16 07:14 UTC] daniel at danielnorton dot com
I suggest changing the title of this to "mt_rand() only reliable when
($max - $min) <= mt_getrandmax ()".
 [2011-12-16 07:14 UTC] daniel at danielnorton dot com
-Summary: mt_rand() poor quality with large magnitude negative $min +Summary: mt_rand() only reliable when ($max - $min) <= mt_getrandmax ()
 [2014-07-31 04:01 UTC] datibbaw@php.net
Can't test this on Windows, but according to 3v4l it can't be reproduced in any of the versions:

http://3v4l.org/anJ6F
 [2015-08-15 10:22 UTC] cmb@php.net
-Status: Open +Status: Duplicate -Assigned To: +Assigned To: cmb
 [2015-08-15 10:22 UTC] cmb@php.net
This issue has the same cause as bug #60543. As the other ticket
is already being worked on (PR #1416), I'm marking this one as
duplicate.
 [2015-08-15 10:23 UTC] cmb@php.net
Oops, I meant bug #63174.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 07:01:30 2024 UTC