简体   繁体   English

修改PHP rand函数

[英]Modifying PHP rand function

For testing and learning purpose, I wanted to modify the php rand and mt_rand functions which are in https://github.com/php/php-src :ext/standard/rand.c. 出于测试和学习的目的,我想修改https://github.com/php/php-src:ext / standard / rand.c中的php randmt_rand函数。

I wanted to give a fixed output each time rand function is called and for this purpose I modified the code 我想在每次调用rand函数时给出一个固定的输出,为此我修改了代码

PHPAPI long php_rand(TSRMLS_D)
{
    long ret;

    if (!BG(rand_is_seeded)) {
        php_srand(GENERATE_SEED() TSRMLS_CC);
    }

#ifdef ZTS
    ret = php_rand_r(&BG(rand_seed));
#else
# if defined(HAVE_RANDOM)
    ret = random();
# elif defined(HAVE_LRAND48)
    ret = lrand48();
# else
    ret = rand();
# endif
#endif

    // ignoring the results coming from the calls above and 
    // returning a constant value 
    ret = 3264;

    return ret;
}

compiled 编译

./configure
make
make install

and finally called the rand function as echo rand(3000,4000); 最后将rand函数称为echo rand(3000,4000); and it always returns 3000 . 它总是返回3000

What would be the way to modify this function? 修改此功能的方法是什么? and why there is TSRMLS_D but not the range parameters? 为什么有TSRMLS_D而不是范围参数?

The actual function that is called from PHP is the one declared PHP_FUNCTION(rand) , which calls the php_rand() function that you modified. 从PHP调用的实际函数是声明为PHP_FUNCTION(rand) php_rand()函数,它调用您修改的php_rand()函数。 It does the following: 它执行以下操作:

PHP_FUNCTION(rand)
{
    long min;
    long max;
    long number;
    int  argc = ZEND_NUM_ARGS();

    if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE)
        return;

    number = php_rand(TSRMLS_C);
    if (argc == 2) {
        RAND_RANGE(number, min, max, PHP_RAND_MAX);
    }

    RETURN_LONG(number);
}

As you can see, if you pass 2 parameters in, it calls the RAND_RANGE macro, which transforms the result of php_rand() into the range given. 如您所见,如果您传入2个参数,则会调用RAND_RANGE宏,该宏将php_rand()的结果转换为给定的范围。

#define RAND_RANGE(__n, __min, __max, __tmax) \
    (__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))

If you want it always to output a given value, I would recommend modifying PHP_FUNCTION(rand) , instead of php_rand() . 如果您希望它始终输出给定值,我建议修改PHP_FUNCTION(rand) ,而不是php_rand()

Though if all you're looking for is stable random number outputs, so that you get the same result every time, if you don't care about the exact result, you can just call srand(0) at the beginning of your program, to seed the random number generator with a constant value. 虽然如果您正在寻找的是稳定的随机数输出,那么每次都得到相同的结果,如果您不关心确切的结果,您可以在程序开头调用srand(0) ,使用常量值为随机数生成器播种。 This will mean that the random number generator will always give you the same sequence of random numbers, which is useful for testing purposes, and can be done without patching PHP itself. 这意味着随机数生成器将始终为您提供相同的随机数序列,这对于测试目的非常有用,并且可以在不修补PHP本身的情况下完成。

Look at the RAND_RANGE macro define in php_rand.h. 查看php_rand.h中的RAND_RANGE宏定义。 It does some additional permutation/scrambling of the input value to make it fit between the range you've specified. 它对输入值进行一些额外的置换/加扰,使其适合您指定的范围。

If you really want the rand() function to return 3264 even if that doesn't fit within the parameters passed to rand(), remove this block in rand.c: 如果你真的希望rand()函数返回3264,即使它不适合传递给rand()的参数,在rand.c中删除这个块:

    if (argc == 2) {
    RAND_RANGE(number, min, max, PHP_RAND_MAX);
}

If you still want to consider min/max, you're going to need to figure out what you want that to actually do if you specify a min/max that doesn't include your hardcoded number. 如果您仍想考虑最小值/最大值,那么如果您指定不包含硬编码的最小值/最大值,您将需要弄清楚您想要实际执行的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM