`
yzd
  • 浏览: 1885538 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

随机生成13位绝对无重复随机数的高效方法

 
阅读更多

问题思路:

1、    预先生成好所有无重复随机数并存储,按需取数;

2、    随机生成,即时比对当前所有已生成数。若存在,则重新生成。

3、    寻找一个好的无冲突的hash算法(或冲突概率较低)。

4、    按照一定的算法来生成伪随机数,要求满足一定数量级内无相似度或较低相似度。

随机就不可能不重复,故任何算法不可能实现真正的随机.只是能够在一定程度上防止高频度的碰撞及相似度,从而给外界一个随机的假像.

 

 

思路一的相关方法及问题:

事先生成1-10000000000000,然后分组打乱,重复若干次后,即可获得所有的10万亿的数据。生成13位数(10万亿)大概是2的43次方,假设我们采用4个bit位存储一个数字(满足能表达数目至少大于九的二进制最小长度),那么一个13位的数需要52bit,即约为7Byte(字节),乘以2的43次方,可以预算整个占用空间约为56TB。无论采用何种存储方式的优化,因为随机化后的相似度极低(动态规划中的邻灰度压缩算法,包括使用数据库)优化后也是TB级的数据量,故此基于此思路上实现方法均是不现实的。

 

思路二的相关方法及问题:

 

1、  数据库用生成序列做主键(由数据库来完成不重复判断),插入失败则说明此数据已存

在,方法实现简单易行。

2、排序随机生成的随机数,采用二分查找法,并插入排序队列中的合适位置。

3、人工生成红黑树(AVL),每次插入时判断是否已存在。

 

此三种方法均可以实现,但是从效率而言第三种方法较好,通过数据库异常来确定数据是否重复性能明显是最差的。相比第二种方法,插入采用链表明显效率更高,但是要实现二分查找的随机访问必须要使用类似数组的序列。固采用第三种红黑树的方法是效率最高的。

 

但是这类方法有一个共同的缺陷,当已经生成好50%以上的数据后,这颗树的查找效率是没有问题的,但是这颗树(或者数组)的大小也快接近TB级了。从这个角度来看反而不如第一种思路实现的方法简单。而且举一个例子,十个数里面如果已经取完八个不同的数据后再生成随机数,那么重复抽到已经生成的那八个数中的一个的概率就非常大了,这样分析后可以得到,每生成一个随机数,需要遍历整颗树的次数会随着树的增大而增大,这是不可以接受的。

 

 

思路三的相关方法及问题:

 

1、依次Hash 1-10000000000000个数字,并将结果进行冲突检测。

2、  MD5类似强Hash算法加密固定区间内的数字,如果出现相同则说明无法逆向解密。(需要采用单向唯一映射修改长度)

3、  GUID的生成方法参考。

 

方法一,需要存储相应的结果来进行冲突检测,类似与思路二中的方法3,存储量非常大。方法二和方法三是同一种问题,MD5加密后是生成16或者32位不重复字符,注意这里是字符(0-9a-zA-Z),而GUID随机生成的是128位的字符,故很难找到一种将16、32甚至128位映射到32位且每一位由62(10+26+26)个字符集映射到10(0-9)位的数字字符集的方法来单向映射如此大的数字集之差。

 

 

思路四的相关方法及问题:

这个思路是我们目前推荐的且易于实现。

 

分段链接法;

 

首先我们将数据划分为6+6+1,这就将我们的数据量缩小到百万级。为什么这样划分,是根据一定的时间效率和后面的链接方法决定的。

 

下面我们来讨论随机生成6位随机数的方法:

 

1000000 个数中生成 100000 位随机数花时3s。

1000000 个数中生成 500000 位随机数花时16s。

1000000 个数中生成 800000 位随机数花时43s。

1000000 个数中生成 900000 位随机数花时 > 1h。

故我们选择第三种方案。

生成的数据截图如下:

 

使用同样的方法再重新生成一个6位随机数。

 

链接方法我们采用横向邻近无关联连接法:

如图:

 

 

(此处不使用数据库笛卡尔乘积,而采用程序读取部分数据,并在数据不足时自动缓存下一部分数据)

固此方法可以得到千亿级内不重复,八十万级数据量内无相似度;(对称链接)。而且对于整个的空间消耗都符合要求。

 

下面是关键的数据库随机选取随机数sql脚本。

 

USE   Job

GO

 

CREATE   TABLE   tb2(id   char(6))

CREATE   UNIQUE   INDEX   IX_tb2   ON   tb2(id)

WITH   IGNORE_DUP_KEY  

GO

 

DECLARE   @dt   datetime

SET   @dt   =   GETDATE()

SET   NOCOUNT   ON

DECLARE   @row   int

SET   @row   =   800000

WHILE   @row   > 0

BEGIN

RAISERROR( 'need   %d   rows ',   10,   1,   @row)   WITH   NOWAIT

SET   ROWCOUNT   @row

INSERT   tb2   SELECT

id   =   RIGHT(100000000   +   CONVERT(bigint,   ABS(CHECKSUM(NEWID()))),  6)

FROM   syscolumns   c1,   sysobjects   o--,   syscolumns   c2

SET   @row   =   @row   -   @@ROWCOUNT

END

SELECT   BeginDate   =   @dt,   EndDate   =   GETDATE(),   Second   =   DATEDIFF(Second,   @dt,   GETDATE())

GO

 

SELECT   COUNT(*)   FROM   tb2

GO

 

数据打乱脚本

select identity(int,1,1)   as   rownumber, * into tmp_tb from tb order by NEWID();

select identity(int,1,1)   as   rownumber, * into tmp_tb2 from tb2 order by NEWID();

 

数据合并采用程序控制:

具体合并方法见上图。要点是记录在第一表中的位置,及错开度N。

0
0
分享到:
评论

相关推荐

    JAVA源码利用随机函数抽取幸运数字JAVA源码利用随机函数抽取幸运数字

    Java中的随机数生成器主要通过java.util.Random类实现,该类基于线性同余生成器算法,可以高效地产生一系列伪随机数。 Random类中有一个重要的方法next(int bits),它返回下一个随机数,该随机数是用一个用户提供的...

    洗牌算法思路讲解(程序员面试题)

    该方法随机生成两个不重复的整数,然后交换它们在数组中的对应元素。重复n次交换操作,理论上n越大,洗牌效果越接近随机。 优点:相比思路1,减少了寻找空位的步骤,降低了时间复杂度。 缺点:需要足够的交换次数以...

    前端开源库-random-unique-id

    `random-unique-id`是一个专为前端设计的开源库,其核心目标是生成不可预测且绝对唯一的128位十六进制ID。这个库采用真随机数生成器作为种子,结合微秒级时间戳和熵计数器来确保生成的ID既具有随机性,又能在短时间...

    BMW.rar_抽奖软件

    这款软件不同于传统的随机数生成方式,它采用了一种更为先进的算法,保证了每次抽奖的结果都是不可预测且绝对随机的。 在IT领域,随机数的生成是至关重要的,特别是在抽奖系统中。一般的随机数生成器可能会存在一定...

    一文说尽64bit素数检测(幂模运算,米勒拉宾算法,双线程)

    64位素数检测通常涉及到高效且精确的方法,因为处理大整数的计算需求日益增长。本文将深入探讨如何检测64位的素数,主要关注幂模运算、米勒-拉宾算法以及双线程应用。 首先,让我们了解幂模运算。在模运算中,幂模...

    j2me试题一本万利,大量试题

    - 键盘事件方法:`keyPressed(int keyCode)`处理按键按下,`keyReleased(int keyCode)`处理按键释放,`keyRepeated(int keyCode)`处理按键重复,`pointerPressed(int x, int y)`处理触摸屏点击,因此选项B正确。...

    高级C语言 学完C语言来看这个绝对收获

    洗牌算法通常用于生成随机排列,实现随机性。 #### 45. 深入理解C语言指针的奥秘 理解指针的工作机制是掌握C语言的关键。 #### 46. 游戏外挂的编写原理 虽然不鼓励编写外挂,但从技术角度理解其原理有助于增强...

    量子计算在密码学中的应用.pptx

    - **利用量子物理的随机性:** 量子力学中存在真正的随机性,这为生成真正随机数提供了可能。 - **增强密码系统的不可预测性:** 由于量子随机数生成器产生的数字是完全随机的,因此极大地提高了密码系统的安全性...

    java面试问题集锦

    `Math.random()`方法用于生成一个大于等于0.0小于1.0的伪随机数。需要注意的是,这个方法的实现依赖于底层平台,因此在某些情况下可能无法提供完全随机的结果。 #### 七、IO ##### 字节流复制文件 复制文件通常...

    【经典源码收藏】基于jQuery的项目常见函数封装集合

    它使用`Math.random()`生成一个0到1之间的随机数,然后通过算术计算返回所需的随机整数。 #### 8. jQuery.mFormatCurrency() - 数值格式化为金额形式 这个函数将数值格式化为带有逗号分隔符的字符串,并保留两位...

    Python基础教程(第二版)(第十-十一章).pdf

    - `os.urandom(n)`:返回指定长度的随机字节,用于生成加密安全的随机数。 5. **fileinput模块**:用于逐行处理多个输入文件。 - `fileinput.input([files[, inplace[, backup]]])`:遍历文件,`inplace=True`时...

Global site tag (gtag.js) - Google Analytics