【青训营】写好JS——保证正确

简介: 【青训营】写好JS——保证正确

在实际项目当中我们经常会出现以下问题:


  • 代码可以跑通,但是业务上总出bug
  • 业务上没有异常,但是代码执行的过程中总是出现异常
  • 代码没问题,测试也没问题,但不能保证正确性,或者说保证公平


一个例子:洗牌



如果让你实现一个洗牌算法,你会怎么实现?


Math.random()


如果使用Math.random()我会这样实现:


const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
function shuffle(cards) {
  return [...cards].sort(() => 
    Math.random() > 0.5 ? -1 : 1
  )
}
console.log(shuffle(cards))
复制代码


写完多运行几次:


image.png


可以看出确实是洗牌了,但是这样随机出来的就公平吗?我们测试一下。


测试


增大测试次数为一百万次,然后记录每个位置出现的数字之和,如果公平的话,这个结果应该都很接近。


const result = Array(10).fill(0);
for(let i = 0; i < 1000000; i++) {
  const c = shuffle(cards);
  for(let j = 0; j < 10; j++) {
    result[j] += c[j];
  }
}
console.log(result);
复制代码


测试结果如图:


image.png


可以看到每个位置的数字之和差距极大,并没有出现接近的情况,所以这个算法确实是一个不公平的算法。


改进


之前的算法之所以出现问题,是因为sort()导致交换的位置不够随机。


我们可以使用一个经典算法进行改进(如果学过概率论应该很熟悉,就是摸球拿了不放回去):


  • 每次随机抽取一张放到最后
  • 剩下的重复第一步即可



image.png

image.png

image.png


而且这个算法可以通过数学归纳法证明每个位置概率都是相等的,写成代码就是这样的:


const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function shuffle(cards) {
  const c = [...cards];
  for (let i = c.length; i > 0; i--) {
    const pIdx = Math.floor(Math.random() * i);
    [c[pIdx], c[i - 1]] = [c[i - 1], c[pIdx]];
  }
  return c;
}
console.log(shuffle(cards));
复制代码


还用上面的测试代码测试一下正确性:


image.png


可以看出来数字都很接近,这个算法就是我们想要的保证正确(公平)的代码。


而且这样写还有一个好处就是:当只需要抽取少量随机牌时,我们并不需要把每张牌都随机一遍(也就是完全洗一遍),性能显然更高。


目录
相关文章
|
3天前
|
Web App开发 JavaScript 前端开发
技术好文共享:非常好的一个JS代码(CJL.0.1.js)
技术好文共享:非常好的一个JS代码(CJL.0.1.js)
|
JavaScript
一道JS题,让我更深刻的理解了JS的执行机制
闲逛摸鱼发现一道有趣的题,题目如下,本来是不想拿出来单独写一篇文章的,因为太短了,但是我需要存在感,沸点没人看,所以还是写一篇文章吧;
60 0
一道JS题,让我更深刻的理解了JS的执行机制
|
前端开发
前端学习案例12-js的执行机制1
前端学习案例12-js的执行机制1
44 0
前端学习案例12-js的执行机制1
|
前端开发
前端学习案例13-js的执行机制2
前端学习案例13-js的执行机制2
45 0
前端学习案例13-js的执行机制2
|
前端开发
前端学习案例1-js的执行机制
前端学习案例1-js的执行机制
49 0
前端学习案例1-js的执行机制
|
JavaScript
js基础笔记学习27-逻辑非
js基础笔记学习27-逻辑非
53 0
js基础笔记学习27-逻辑非
|
JavaScript
JS查漏补缺——神奇的this
JS查漏补缺系列是我在学习JS高级语法时做的笔记,通过实践费曼学习法进一步加深自己对其的理解,也希望别人能通过我的笔记能学习到相关的知识点。这一次我们来理解一下面试题常考的this的指向
107 0
|
JavaScript
一道有趣Js面试题,你有几种办法解决?
引子: 今天写了手撕instanceof,以我的风格来说,再写一篇今天已经算是高产了~但是,我真的忍不住想把这个题给大家分享一下,特别有意思,e.g. 说 var 一个 a 等于什么的时候,它即1,又2,还==3 ?
71 0
|
JavaScript
【青训营】写好JS——写代码最应该关注什么?
【青训营】写好JS——写代码最应该关注什么?
96 0
【青训营】写好JS——写代码最应该关注什么?
|
JavaScript 测试技术
【青训营】写好JS——过程抽象
【青训营】写好JS——过程抽象
216 0
【青训营】写好JS——过程抽象