资讯专栏INFORMATION COLUMN

关于JavaScript中的随机数方法

liuyix / 3385人阅读

摘要:另外,这几篇几个不错的随机生成随机数采用对获取的浮点数进行取整操作,也是同样的问题,能取到左端点,却无法取到右端点。

最近在琢磨内置对象Math的时候,参考了很多网上资料,不过我在Google中搜索js 随机整数,出来很多博客文章,很遗憾,在我看来排名靠前的这些文章都是错误的。接下来我将会论证我这一观点,同时把我所理解的Math.random()方法跟你分享。

获取端点问题; 先看这一篇,Javascript实现随机整数。

在这篇文章中,作者给出了如下方法,根据他的文章描述,这个算法能产生startend之间的随机整数。

javascriptfunction rnd(start, end){
    return Math.floor(Math.random() * (end - start) + start);
}
一个需要确认的问题

在说我的观点之前,我希望先明确一件事情,设想别人跟你提了一个需求:

  

需要一个生成ab之间随机整数的方法。

这时候我觉得你至少需要跟对方确认一个问题:包不包括两个端点,即ab ?
(其实还有一些问题需要考虑的,比如传入的ab如果不是数字类型?如果是小数?如果是负数?如果ab大?为了专注本文要讨论的内容,我们假定传入的ab都是合法的正整数,且a<b。)

如果对方给你确认了,那是坠吼的;但是如果对方没有确认,如何理解这一需求?我认为在对上述需求没有更多说明的情况下,以下两个是靠谱的理解:

  

既要包括端点a,也要包括端点b

既不包括端点a,也不包括端点b

所以,如果你实现的方法能获取的只包含其中一个端点,我觉得这种实现是不太理想的,你再琢磨这句话:ab之间的随机整数

如果你也认同我的这段论述,接下来回到开头那个方法,看他能不能实现获取从startend之间的随机整数;方法主体就一个运算表达式:

javascriptreturn Math.floor(Math.random() * (end - start) + start);

逐步分析:

javascriptMath.random();                               //[0,1)
Math.random()*(end-start);                   //[0,end-start);
Math.random()*(end-start)+start;             //[start,end);
Math.floor(Math.random()*(end-start)+start); //{ x | x>=start,x

第一行,Math.random()方法返回的是01之间的浮点数,注意,__包括0,不包括1!__ECMA语言标准里明确规定了:

  

Returns a Number value with positive sign, greater than or equal to 0 but less than 1

所以,这篇博客,和这篇博客是不正确的;由于这两篇占据结果第一页的博文比较古老,我甚至在想是不是ECMA标准一开始不是这样子的,然后查了一下,ECMA标准从第一个版本对random方法的规定就是现在这个样子。

第二行,Math.random()*(end-start);则返回0end-start之间的浮点数,包含0,不包含end-start

第三行, Math.random()*(end-start)+start;返回startend之间的浮点数,包含start,不包含end

第四行,Math.floor(Math.random()*(end-start)+start);。这是最关键的一行,对上一行产生的浮点数进行向下取整,既然是向下取整,结果可能取到start,却永远取不到end

根据前述理解,这样的实现我认为是不合要求的。所以,这篇文章也是不正确的。
另外,这几篇几个不错的JavaScript随机...、js生成随机数采用parseInt对获取的浮点数进行取整操作,也是同样的问题,能取到左端点,却无法取到右端点。parseInt操作浮点数的效果相当于Math.floor()

  勘误:
  
  

之前写的上面这句话“parseInt操作浮点数的效果相当于Math.floor()”,我在看了这篇文章之后发现这句话是不对的,抱歉。但我的结论是不变的:Math.random()的结果范围包括0,因此parseInt(Math.random())也可能取到0

而这一篇JavaScript random方法得到随机整数,采用的是Math.ceil()方法进行向上取整,

javascriptMath.ceil(Math.random()*3);//得到1-3的整数

这样确实既能取到右端点,也能取到左端点,但是作者的左端点标错了,这个是有可能能取到0的,尽管取到0的概率是无限趋近于0;

这样引伸出另一个问题:取得的随机整数范围里,各整数出现的概率是否一致?

获取概率问题 一个概率不均等的方法

在之前有位老师给出的获取随机数方法是下面这样(要求了必须包括端点);

javascriptfunction getRandom(n,m){
  //省略特殊情形下的处理过程,比如n>m,或者n、m之一无法转化为有效数字;
  return Math.round(Math.random()*(m-n)+n);
}

一个获取随机整数的方法,如果不格外的声明,我觉得有一个默认的条件应该是:

  

生成每个整数的概率应当是均等的;

根据第一部分的分析,这个方法能获取的浮点数的范围是nm之间,包括n,不包括m;而这个方法中取整是采用Math.round()四舍五入;这样的话:

  

当取出的结果x∈[n,n+0.5)时,会四舍五入为n;区间范围为0.5,概率为0.5/(m-n)*100%;

当取出的结果x∈[n+0.5,n+1.5)时,会四舍五入为n+1;区间范围为1,概率为1/(m-n)*100%;

当取出的结果x∈[n+1.5,n+2.5)时,会四舍五入为n+2;区间范围为1,概率为1/(m-n)*100%;

......

当取出的结果x∈[m-0.5,m)时,会四舍五入为m;区间范围为0.5,概率为0.5/(m-n)*100%;

通过以上分析,该算法确实可以达到目标,取到nm之间的随机整数,但是并不是每个整数出现的概率都是相等的,具体来说,取得两边端点的整数概率是其他数字的一半。所以,我认为这也是不够完美的。

这样的话,在写一个获得概率均等的随机整数方法的时候,相信你知道应该注意些什么问题了吧。

总结

总结一下,当我们在获取随机整数的时候,有两个问题需要特别注意:

  

一定要仔细检查两边端点是否是否能取到?是否与需求一致?

获取到的每个整数的概率是否均等?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85809.html

相关文章

  • JavaScript标准库系列——Math对象和Date对象(二)

    摘要:目录导语对象对象对象方法的应用日历插件小结导语这是标准库系列的第二篇文章,主要讨论一下对象和对象,对象在平时处理一些数学操作时能起到事半功倍的作用,目前小羊接触到的对象的使用场景是动画制作对象作为关于时间的接口,能够将其应用于制作和时间相关 目录 导语 1. Math对象 2. Date对象 3. Date对象方法的应用——日历插件; 4. 小结 导语 这是《JavaScript标准...

    whinc 评论0 收藏0
  • 关于Number】JavaScript关于Number的操作

    摘要:字符串与数字间的转换结果结果结果结果注意会把一个类似于的字符串强制转换成判断是否为有效的数字某些方法如会返回一个特殊的值请注意第点中的注意此方法不完全适合判断一个字符串是否是数字型小数转整数结果四舍五入结果返回大于的最小整数结果返回小于的最 1.字符串与数字间的转换 var i = 1; var str = i.toString(); //结果: 1 var str...

    zhaofeihao 评论0 收藏0
  • 也谈前端面试常见问题之『数组乱序』

    摘要:看完部分的源码,首先迫不及待想跟大家分享的正是本文主题数组乱序。这是一道经典的前端面试题,给你一个数组,将其打乱,返回新的数组,即为数组乱序,也称为洗牌问题。关于数组乱序,正确的解法应该是,复杂度。 前言 终于可以开始 Collection Functions 部分了。 可能有的童鞋是第一次看楼主的系列文章,这里再做下简单的介绍。楼主在阅读 underscore.js 源码的时候,学到...

    tracy 评论0 收藏0
  • 浅谈前端安全

    摘要:安全问题的分类按照所发生的区域分类后端安全问题所有发生在后端服务器应用服务当中的安全问题前端安全问题所有发生在浏览器单页面应用页面当中的安全问题按照团队中哪个角色最适合来修复安全问题分类后端安全问题针对这个安全问题,后端最适合来修复前端安全 安全问题的分类 按照所发生的区域分类 后端安全问题:所有发生在后端服务器、应用、服务当中的安全问题 前端安全问题:所有发生在浏览器、单页面应用、...

    Cympros 评论0 收藏0
  • 浅谈前端安全

    摘要:安全问题的分类按照所发生的区域分类后端安全问题所有发生在后端服务器应用服务当中的安全问题前端安全问题所有发生在浏览器单页面应用页面当中的安全问题按照团队中哪个角色最适合来修复安全问题分类后端安全问题针对这个安全问题,后端最适合来修复前端安全 安全问题的分类 按照所发生的区域分类 后端安全问题:所有发生在后端服务器、应用、服务当中的安全问题 前端安全问题:所有发生在浏览器、单页面应用、...

    李世赞 评论0 收藏0

发表评论

0条评论

liuyix

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<