diff options
author | Rasmus Lerdorf <rasmus@php.net> | 1999-07-24 02:30:37 +0000 |
---|---|---|
committer | Rasmus Lerdorf <rasmus@php.net> | 1999-07-24 02:30:37 +0000 |
commit | 8de073782c03c361c507129733227f3c3315d214 (patch) | |
tree | ee221838c20aea89fea2d22674a54d9e1417871b /ext/standard/rand.c | |
parent | cd8d7c7c8a73cc7b2c1302051833716b40092930 (diff) | |
download | php-git-8de073782c03c361c507129733227f3c3315d214.tar.gz |
Bring rand.c up to date
Diffstat (limited to 'ext/standard/rand.c')
-rw-r--r-- | ext/standard/rand.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/ext/standard/rand.c b/ext/standard/rand.c index 09d28b6d65..051eab8ce6 100644 --- a/ext/standard/rand.c +++ b/ext/standard/rand.c @@ -201,6 +201,8 @@ static inline uint32 randomMT(void) #define PHP_RAND_MAX RAND_MAX #endif +/* {{{ proto void srand(int seed) + Seeds random number generator */ PHP_FUNCTION(srand) { pval *arg; @@ -219,7 +221,10 @@ PHP_FUNCTION(srand) #endif #endif } +/* }}} */ +/* {{{ proto void mt_srand(int seed) + Seeds Mersenne Twister random number generator */ PHP_FUNCTION(mt_srand) { pval *arg; @@ -229,7 +234,10 @@ PHP_FUNCTION(mt_srand) convert_to_long(arg); seedMT(arg->value.lval); } +/* }}} */ +/* {{{ proto int rand([int min, int max]) + Returns a random number */ PHP_FUNCTION(rand) { pval *p_min=NULL, *p_max=NULL; @@ -262,13 +270,40 @@ PHP_FUNCTION(rand) return_value->value.lval = rand(); #endif #endif - + /* + * A bit of tricky math here. We want to avoid using a modulus because + * that simply tosses the high-order bits and might skew the distribution + * of random values over the range. Instead we map the range directly. + * + * We need to map the range from 0...M evenly to the range a...b + * Let n = the random number and n' = the mapped random number + * + * Then we have: n' = a + n(b-a)/M + * + * We have a problem here in that only n==M will get mapped to b which + # means the chances of getting b is much much less than getting any of + # the other values in the range. We can fix this by increasing our range + # artifically and using: + # + # n' = a + n(b-a+1)/M + * + # Now we only have a problem if n==M which would cause us to produce a + # number of b+1 which would be bad. So we bump M up by one to make sure + # this will never happen, and the final algorithm looks like this: + # + # n' = a + n(b-a+1)/(M+1) + * + * -RL + */ if (p_min && p_max) { /* implement range */ return_value->value.lval = p_min->value.lval + - (int)((double)p_max->value.lval * return_value->value.lval/(PHP_RAND_MAX+(double)p_min->value.lval)); + (int)((double)(p_max->value.lval - p_min->value.lval + 1) * return_value->value.lval/(PHP_RAND_MAX+1.0)); } } +/* }}} */ +/* {{{ proto int mt_rand([int min, int max]) + Returns a random number from Mersenne Twister */ PHP_FUNCTION(mt_rand) { pval *p_min=NULL, *p_max=NULL; @@ -304,16 +339,23 @@ PHP_FUNCTION(mt_rand) if (p_min && p_max) { /* implement range */ return_value->value.lval = p_min->value.lval + - (int)((double)p_max->value.lval * return_value->value.lval/(PHP_RAND_MAX+(double)p_min->value.lval)); + (int)((double)(p_max->value.lval - p_min->value.lval + 1) * return_value->value.lval/(PHP_RAND_MAX+1.0)); } } +/* }}} */ +/* {{{ proto int getrandmax(void) + Returns the maximum value a random number can have */ PHP_FUNCTION(getrandmax) { return_value->type = IS_LONG; return_value->value.lval = PHP_RAND_MAX; } +/* }}} */ + +/* {{{ proto int mt_getrandmax(void) + Returns the maximum value a random number from Mersenne Twister can have */ PHP_FUNCTION(mt_getrandmax) { return_value->type = IS_LONG; @@ -323,7 +365,7 @@ PHP_FUNCTION(mt_getrandmax) */ return_value->value.lval = 2147483647; /* 2^^31 */ } - +/* }}} */ /* * Local variables: * tab-width: 4 |