PHP 随机数 C扩展随机数

由于要用到固定长度的随机字符串。

首先是一段PHP代码

$str_md5=md5(uniqid());
  $rand = mt_rand(1, 28);
  $str1=substr($str_md5,$rand,6);
  $rand = mt_rand(1, 28);
  $str2=substr($str_md5,$rand,6);
  $rand = mt_rand(1, 28);
  $str3=substr($str_md5,$rand,6);
  $code=substr($str1.$str2.$str3,0,8);

生成180000个随机字符串,图中是按照重复数量倒序排列,可以看到基本都有重复的。不过也是比较理想的。

由于想提升一下自己的C语言能力,所以用C重新写了一下随机生成字符串。

其中用到了随机数函数srand(),rand();

不过折腾一两个小时,随机数还是有问题。并发访问时时间可能几乎为同时,那么srand给的种子时间可以视为相同的。这样就导致了,产生的随机数也是一样的。从而产生的随机字符串也是一样的。循环输出随机字符串,几乎都是一模一样的。

后来想到了ukey,这个扩展可以实现唯一的ID,那么访问都产生唯一的ID,是不是可以将这个ID作为种子时间。答案是肯定的。

上图是产生的随机字符串,可以自定义长度。也同样可以输出只有数字的字符串。相较PHP所产生的随机字符串重复率更低且速度更快。

 PHP_FUNCTION(get_random__num_str)
{
   int length=8;

   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE)
   {
    length=8;

   }
   length++;
  int flag, i;
  char* string;
  __uint64_t timestamp = realtime();
  __uint64_t retval;
  int len;
  char buf[128];

  if (timestamp == 0ULL) {
    RETURN_FALSE;
  }

  spin_lock(lock, pid);

  if (context->last_timestamp == timestamp) {
    context->sequence = (context->sequence + 1) & context->sequence_mask;
    if (context->sequence == 0) {
      timestamp = skip_next_millis();
    }

  } else {
    context->sequence = 0; /* Back to zero */
  }

  context->last_timestamp = timestamp;

  retval = ((timestamp - context->twepoch) << context->timestamp_left_shift)
      | (context->datacenter_id << context->datacenter_id_shift)
      | (worker_id << context->worker_id_shift)
      | context->sequence;

  spin_unlock(lock, pid);
  //printf('%ld',retval);
  srand((unsigned)retval);
  //srand((unsigned) time(NULL ));
  if ((string = (char*) emalloc(length)) == NULL )
  {
    //myLog("Malloc failed!flag:14\n");
    RETURN_NULL() ;
  } 

  for (i = 0; i < length - 1; i++)
  {
    flag = rand() % 3; 

    switch (flag)
    {
      case 0:
        string[i] = '1' + rand() % 5;
        break;
      case 1:
        string[i] = '2' + rand() % 7;
        break;
      case 2:
        string[i] = '0' + rand() % 10;
        break;
      default:
        string[i] = '9';
        break;
    } 

  }
  string[length - 1] = '\0';
  RETURN_STRINGL(string,length,0);
}
 PHP_FUNCTION(get_random_str)
{
   int length=8;

   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE)
   {
    length=8;

   }
   length++;
  int flag, i;
  char* string;
  __uint64_t timestamp = realtime();
  __uint64_t retval;
  int len;
  char buf[128];

  if (timestamp == 0ULL) {
    RETURN_FALSE;
  }

  spin_lock(lock, pid);

  if (context->last_timestamp == timestamp) {
    context->sequence = (context->sequence + 1) & context->sequence_mask;
    if (context->sequence == 0) {
      timestamp = skip_next_millis();
    }

  } else {
    context->sequence = 0; /* Back to zero */
  }

  context->last_timestamp = timestamp;

  retval = ((timestamp - context->twepoch) << context->timestamp_left_shift)
      | (context->datacenter_id << context->datacenter_id_shift)
      | (worker_id << context->worker_id_shift)
      | context->sequence;

  spin_unlock(lock, pid);
  //printf('%ld',retval);
  srand((unsigned)retval);
  //srand((unsigned) time(NULL ));
  if ((string = (char*) emalloc(length)) == NULL )
  {
    //myLog("Malloc failed!flag:14\n");
    RETURN_NULL() ;
  } 

  for (i = 0; i < length - 1; i++)
  {
    flag = rand() % 3; 

    switch (flag)
    {
      case 0:
        string[i] = 'A' + rand() % 26;
        break;
      case 1:
        string[i] = 'a' + rand() % 26;
        break;
      case 2:
        string[i] = '0' + rand() % 10;
        break;
      default:
        string[i] = 'x';
        break;
    } 

  }
  string[length - 1] = '\0';
  RETURN_STRINGL(string,length,0);
}

上图是PHP生成18W随机字符串所用的时间

上图是C扩展生成18W随机字符串所用的时间

所用的服务器都是1G内存 双核的阿里云服务器。

只要在ukey中加入上如代码就可以生产随机字符串和随机长度数字字符串,PHP唯一ID生成扩展ukey。

php.ini的配置项:

[ukey]
ukey.datacenter = integer
ukey.worker = integer
ukey.twepoch = uint64

datacenter配置项是一个整数, 用于设置数据中心;
worker配置项是一个整数, 用于设置数据中心的机器序号;
twepoch配置项是一个64位的整数, 用于设置时间戳基数, 此值越大, 生成的ID越小;

安装:

$ cd ./ukey
$ phpize
$ ./configure
$ make
$ sudo make install 

Ukey提供3个有用的函数:

ukey_next_id() -- 用于生成唯一ID
ukey_to_timestamp(ID) -- 用于将ID转换成时间戳
ukey_to_machine(ID) -- 用于将ID转换成机器信息

使用实例:

<?php
$id = ukey_next_id();
echo $id;

$timestamp = ukey_to_timestamp($id);
echo date('Y-m-d H:i:s', $timestamp);

$info = ukey_to_machine($id)
var_dump($info);
?>

以上就是本文的全部内容,希望对大家的学习有所帮助。

(0)

相关推荐

  • PHP产生不重复随机数的5个方法总结

    无论是Web应用,还是WAP或者移动应用,随机数都有其用武之地.在最近接触的几个小项目中,我也经常需要和随机数或者随机数组打交道,所以,对于PHP如何产生不重复随机数常用的几种方法小结一下(ps:方法1.4.5是我常用的,其余来自网络整理) 方法一: 复制代码 代码如下: <?php $numbers = range (1,50); //shuffle 将数组顺序随即打乱 shuffle ($numbers); //array_slice 取该数组中的某一段 $num=6; $result =

  • php产生随机数的两种方法实例代码 输出随机IP

    分享下php生成随机数的三种方法,生成1-10之间的不重复随机数,php生成不重复随机数的例子,需要的朋友参考下. 如何用php生成1-10之间的不重复随机数? 例1,使用shuffle函数生成随机数. <?php $arr=range(1,10); shuffle($arr); foreach($arr as $values) { echo $values." "; } ?> 例2,使用array_unique函数生成随机数. <?php $arr=array();

  • php生成随机数或者字符串的代码

    $len表示长度,代码如下: 复制代码 代码如下: /** * 产生随机字符串 * * 产生一个指定长度的随机字符串,并返回给用户 * * @access public * @param int $len 产生字符串的位数 * @return string */ function randstr($len=6) { $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz0123456789-@#~'; // characters

  • php 随机数的产生、页面跳转、件读写、文件重命名、switch语句

    复制代码 代码如下: <?php num = rand(1,5); witch($num){ case 1: $fp1=fopen("f1.dat",'r'); $oname = fgets($fp1); $nname = date("YmdHis"); rename($oname,$nname); fclose($fp1); unlink("f1.dat"); $fp1=fopen("f1.dat",'w'); fwr

  • PHP生成指定长度随机数最简洁的方法

    刚才在写短信验证码模块,需要用到指定位数的随机数,然后网上一找发现太可怕了这么简单的事情竟然用了好几十行多个循环嵌套--看来没有好脑仁儿真的不适合当程序员. 自写了一行版本: function generate_code($length = 4) { return rand(pow(10,($length-1)), pow(10,$length)-1); } 为了便于理解,同时也为了这篇水文可以凑点字数,这是多行版: function generate_code($length = 4) { $

  • php生成随机数的三种方法

    如何用php生成1-10之间的不重复随机数? 例1,使用shuffle函数生成随机数. <?php $arr=range(1,10); shuffle($arr); foreach($arr as $values) { echo $values." "; } ?> 例2,使用array_unique函数生成随机数. <?php $arr=array(); while(count($arr)<10) { $arr[]=rand(1,10); $arr=array_

  • php获取四位字母和数字的随机数的实现方法

    那么我们知道在php中简单的四位数的纯数字验证可以用rand(1000,9999)就可以了,但如果我们要得到字母和数字的随机四位数,那我们该如何写函数呢?下面胡鹏博客在php资料栏目下给出一个完整的实例. <?php function GetfourStr($len) { $chars_array = array( "0", "1", "2", "3", "4", "5", &qu

  • PHP n个不重复的随机数生成代码

    复制代码 代码如下: <?php //range 是将1到100 列成一个数组 $numbers = range (1,100); //shuffle 将数组顺序随即打乱 shuffle ($numbers); //array_slice 取该数组中的某一段 $no=6; $result = array_slice($numbers,0,$no); for ($i=0;$i<$no;$i++){ echo $result[$i]."<br>"; } print_

  • PHP生成不重复随机数的方法汇总

    无论是Web应用,还是WAP或者移动应用,随机数都有其用武之地.在最近接触的几个小项目中,我也经常需要和随机数或者随机数组打交道,所以,对于PHP如何产生不重复随机数常用的几种方法小结一下. 方法一: 复制代码 代码如下: <?php $numbers = range (1,50); //shuffle 将数组顺序随即打乱 shuffle ($numbers); //array_slice 取该数组中的某一段 $num=6; $result = array_slice($numbers,0,$n

  • PHP 随机数 C扩展随机数

    由于要用到固定长度的随机字符串. 首先是一段PHP代码 $str_md5=md5(uniqid()); $rand = mt_rand(1, 28); $str1=substr($str_md5,$rand,6); $rand = mt_rand(1, 28); $str2=substr($str_md5,$rand,6); $rand = mt_rand(1, 28); $str3=substr($str_md5,$rand,6); $code=substr($str1.$str2.$str3

  • PHP随机数 C扩展随机数

    由于要用到固定长度的随机字符串. 首先是一段PHP代码 $str_md5=md5(uniqid()); $rand = mt_rand(1, 28); $str1=substr($str_md5,$rand,6); $rand = mt_rand(1, 28); $str2=substr($str_md5,$rand,6); $rand = mt_rand(1, 28); $str3=substr($str_md5,$rand,6); $code=substr($str1.$str2.$str3

  • Python如何生成随机数及random随机数模块应用

    目录 1.随机生成0-1的浮点数random.random 2.随机生成指定范围内的浮点数random.uniform 3.随机生成指定范围整数random.randint 4.随机从给定集合中生成数random.randrange 5.从序列中获取一个随机元素random.choice 6.随机打乱给定序列的顺序random.shuffle 7.随机获取序列中多个元素random.sample 8.随机数常用函数大全 1.随机生成0-1的浮点数random.random random.rand

  • PHP生成随机数的方法总结

    第一种方法用mt_rand() function GetRandStr($length){ $str='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $len=strlen($str)-1; $randstr=''; for($i=0;$i<$length;$i++){ $num=mt_rand(0,$len); $randstr .= $str[$num]; } return $randstr; } $numb

  • C#实现随机数产生类实例

    本文实例讲述了C#实现随机数产生类.分享给大家供大家参考.具体分析如下: 这个类主要扩展的random的使用,对一个经常需要使用的随机数生成进行了封装,可以产生指定范围内的随机数,可以随机生成字符串等 using System; namespace DotNet.Utilities { /// <summary> /// BaseRandom /// 产生随机数 /// /// 随机数管理,最大值.最小值可以自己进行设定. /// </summary> public class B

  • Java 17 随机数生成器来了一波稳稳的增强

    目录 Java 17 更新更快的 LTS 节奏 Java 17 更新后的 strictfp 关键字 这一条更新来自: JEP 356: Enhanced Pseudo-Random Number Generators ,相比之下,这一条实用多了. 我们都用过随机数,不过一般情况下我们很少去认真的对待随机数的具体结果,就好像它是真的随机一样. var random = new Random(System.currentTimeMillis()); for (int i = 0; i < 10; i

  • C语言中用于产生随机数的函数使用方法总结

    在UNIX操作系统和window的操作系统上,我们知道有一个函数rand,它就是用来产生随机数的函数API接口,那么它的原理如何实现? 如果约定a1=f(seed),an+1=f(an),那么可以得到一个序列a1,a2,a3..an,那么要制作一个伪随机函数rand,只需要让它每调用一次就返回序列的下一个元素就行.其实就是相当于第1次调用rand返回a1,第2次返回a2,-,第n次返回an,这样每次返回的数值都不一样,也就是相当于随机数了.但是其实不是真正的随机数,真正的随机数是使用物理现象产生

  • C#生成指定范围内的不重复随机数

    C#生成指定范围内的不重复随机数 // Number随机数个数 // minNum随机数下限 // maxNum随机数上限 public int[] GetRandomArray(int Number,int minNum,int maxNum) { int j; int[] b=new int[Number]; Random r=new Random(); for(j=0;j<Number;j++) { int i=r.Next(minNum,maxNum+1); int num=0; for

  • 用C#生成不重复的随机数的代码

    对于随机数,大家都知道,计算机不 可能产生完全随机的数字,所谓的随机数发生器都是通过一定的算法对事先选定的随机种子做复杂的运算,用产生的结果来近似的模拟完全随机数,这种随机数被称 作伪随机数.伪随机数是以相同的概率从一组有限的数字中选取的.所选数字并不具有完全的随机性,但是从实用的角度而言,其随机程度已足够了.伪随机数的选 择是从随机种子开始的,所以为了保证每次得到的伪随机数都足够地"随机",随机种子的选择就显得非常重要.如果随机种子一样,那么同一个随机数发生器产生 的随机数也会一样.

  • javascript 随机数 与高级应用 附vbscript(asp) 随机数总结

    一.是javascript 随机数函数Math.random()  生成指定范围的随机数 Math.random()方法没有参数,返回0~1之间的随机数,如果要生成0~n之间的随机 数,可以使用下面的格式: Math.floor(Math.random()*n) 若要生成m~n之间的随机数,可以用: Math.floor(Math.random()*n)+m 下面是运用: ") //生成1~10之间的随机数目 var j = Math.floor(Math.random()*10)+1; doc

随机推荐