note 117249 added to language.types.integer
| From: | dewi at dewimorgan dot com | Date: | Sat, 09 May 2015 19:41:58 +0000 |
| Subject: | note 117249 added to language.types.integer | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-202483@lists.php.net to get a copy of this message | ||
Note that the soft-typing of numbers in PHP means that some things become very difficult. For
example, efficiently emulating the more common linear congruential generators (LCGs) for fast,
deterministic, pseudo-randomness. The naive code to create the next value in a sequence (for
power-of-2 values of $m) is:
$seed = ($seed * $a + $c) % $m;
...where $m, $a, and $c are values and data types carefully chosen such that repeating this
operation will eventually generate every value in the range $0 to $m, with no repetition.
I can find no good commonly used LCGs which use PHP-compatible values. The LCG values used in by
rand() in systems like Borland Delphi, Virtual Pascal, MS Visual/Quick C/C++, VMS's MTH$RANDOM,
old versions of glibc, Numerical Recipes, glibc, GCC, ANSI C, Watcom, Digital Mars, CodeWarrior, IBM
VisualAge C/C++, java.util.Random, Newlib, MMX... *all* fail when ported, for one of two reasons,
and sometimes both:
- In PHP on 32 bit machines and all Windows machines, $m = 2^32 or larger requires UInt or even
UInt64, or the result becomes negative.
- Large $a multiplied by an integer seed gets converted to a float64, but the number can be too long
for the 53-bit mantissa, and it drops the least significant digits... but the LCG code above
requires that the most significant digits should be lost.
These are two classes of problem to beware of when porting integer math to PHP, and I see no clean
and efficient way to avoid either one.
So if designing a cross-platform system that must work in PHP, you must select LCG values that fit
the following criteria:
$m = 2^31 or less (PHP limitation). Recommend: 2^31.
$a = Less than 2^22 (PHP limitation); $a-1 divisible by all prime factors of $m; $a-1 divisible by 4
if $m is. Recommend: 1+(4*(any prime <= 1048573)).
$c = smaller than (2^53-($m*$a)) (PHP limitation); relatively prime with $m. Recommend: any prime
<= 23622320123.
----
Server IP: 72.52.91.14
Probable Submitter: 2605:6000:f4cc:be00:fc0e:1702:46f5:1a63
----
Manual Page -- http://php.net/manual/en/language.types.integer.php
Edit -- https://master.php.net/note/edit/117249
Del: integrated -- https://master.php.net/note/delete/117249/integrated
Del: useless -- https://master.php.net/note/delete/117249/useless
Del: bad code -- https://master.php.net/note/delete/117249/bad+code
Del: spam -- https://master.php.net/note/delete/117249/spam
Del: non-english -- https://master.php.net/note/delete/117249/non-english
Del: in docs -- https://master.php.net/note/delete/117249/in+docs
Del: other reasons-- https://master.php.net/note/delete/117249
Reject -- https://master.php.net/note/reject/117249
Search -- https://master.php.net/manage/user-notes.php