V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fyyz
V2EX  ›  程序员

为什么大多数编程语言,尤其是编译型的,在生成随机数前都要设一个种子?

  •  1
     
  •   fyyz · 2016-08-16 20:41:23 +08:00 · 5737 次点击
    这是一个创建于 2822 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我理解随机数的基本原理,就是一个函数,例如 y=x+1 ,当我给出种子 x=1 的时候就生成结果 y=2 ,只不过生成随机数的函数更加复杂,其结果图像更是随机分布的点,而绝对不会像刚刚例子里举的 y=x+1 那样能画出连续的线。

    但是,令我比较奇怪的是,绝大多数编程语言,尤其是编译型的,必须在生成随机数前进行类似 init() 之类的初始化操作,同时传入一个种子,比如说时间戳之类的,然后才能生成随机数。为什么这些编程语言不会在标准库的随机数函数里内置一个诸如时间戳获取器之类的种子生成器,而一定要程序员手动初始化呢?
    18 条回复    2016-08-17 13:35:53 +08:00
    bombless
        1
    bombless  
       2016-08-16 20:49:07 +08:00 via Android
    这跟语言有啥关系……这明明就是算法设计。

    这是因为最
    vitovan
        2
    vitovan  
       2016-08-16 20:49:37 +08:00
    这是个好问题,待我去搜一搜。
    ehs2013
        3
    ehs2013  
       2016-08-16 20:50:55 +08:00
    随机数被猜到就不好了。针对随机数生成器的攻击太多了
    bombless
        4
    bombless  
       2016-08-16 20:52:30 +08:00 via Android   ❤️ 1
    因为最保险的获取种子的方式是由操作系统收集系统的熵。但是刚启动的时候系统积累的数据不足以收集这些信息,要等系统用一段时间才行。如果你的库需要随机数,那么给它一个种子就绕过了这个难题:库设计者把刚启动时没有合适的种子的困难丢给了调用者。
    Kisesy
        5
    Kisesy  
       2016-08-16 20:54:24 +08:00   ❤️ 3
    shippo7
        6
    shippo7  
       2016-08-16 20:57:41 +08:00 via iPhone
    如果使用当前系统时间作为种子,随机数可以被预测
    debiann
        7
    debiann  
       2016-08-16 21:02:26 +08:00 via iPhone
    如果我需要复现随机数序列呢。把两个问题分开处理不是更灵活吗
    vitovan
        8
    vitovan  
       2016-08-16 21:02:54 +08:00
    r#5 @Kisesy 五楼正解。
    starsoi
        9
    starsoi  
       2016-08-16 21:13:08 +08:00
    让程序员给种子的目的就是为了使程序的行为是可以复现的。
    给定一个种子,随机数生成器生成的随机数序列是固定不变的。在调试程序的时候,给一个固定的种子,保证每次程序跑的时候使用的是相同的随机数序列。因为可能有些 BUG 只有在特定的随机数时才会触发,我就能保证在调试的时候每次跑都会触发这个 BUG 。如果标准库内置了变化的种子(比如用时间戳)而无法人为固定,那你就会发现,你的程序有的时候没 BUG ,有的时候有 BUG , BUG 的复现不受你的控制,从而大大增加了调试的难度。
    当然,调试完成后,用于生产环境中的程序还是得用非固定值(比如时间戳)来作为种子。
    binux
        10
    binux  
       2016-08-16 21:18:03 +08:00   ❤️ 1
    首先,指定随机种子的函数是有必要提供的,比如测试时想要 mock 掉随机状态。
    其次,你也可以不初始化啊,结果不过相当于 srand(1) 罢了。
    最后, rand 一般都是独立的函数,如果要用当前时间作为参数调用 srand ,那么它应该在什么时候调用呢?程序运行时,那如果不用也要初始化吗?函数第一次运行时,检测多麻烦啊。那不如干脆什么都不做,默认固定值好了。
    ecloud
        11
    ecloud  
       2016-08-16 21:36:28 +08:00
    编译型语言一样有现成的第三方库,包括随机字符串,随机整数直接拿来就用,比如 Glib ,还有早年的 Delphi
    uyhyygyug1234
        12
    uyhyygyug1234  
       2016-08-16 21:51:32 +08:00 via Android
    解耦
    zhuangzhuang1988
        13
    zhuangzhuang1988  
       2016-08-16 22:06:53 +08:00
    因为解释性语言已经被初始化了啊,
    如 python 代码
    https://github.com/python/cpython/blob/master/Modules/main.c#L378
    wodesuck
        14
    wodesuck  
       2016-08-16 22:07:22 +08:00
    设置同一个种子可以产生相同的随机数
    比如游戏中,多个玩家可以输入相同的种子来获得完全相同的随机地图
    weyou
        15
    weyou  
       2016-08-16 22:42:00 +08:00
    因为他们都是伪随机数
    wizardoz
        16
    wizardoz  
       2016-08-16 22:52:27 +08:00
    如果一个库生成随机数时自动在后台调用 time() 函数作为种子。那么用这个库开发出的软件,只要提供一个虚假的 time() 函数调用接口给他,每次都给他一个固定的 时间值(或者每次运行软件之前修改系统时间到一个特定的值),那么这个软件就每次随机数都得到同一个结果。你觉得这样的库有人敢用吗?
    fuyufjh
        17
    fuyufjh  
       2016-08-17 13:17:27 +08:00
    @weyou 正解
    lizon
        18
    lizon  
       2016-08-17 13:35:53 +08:00
    把生成的随机序列可否被预测,这个选项留给使用者,因为有时候需要能重现生成的随机序列,比如:游戏战斗回放
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3362 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 12:51 · PVG 20:51 · LAX 05:51 · JFK 08:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.