随机方法总结

2,388 阅读3分钟

说起随机,你可能马上想到 -random (Dota 里面初始化通过random命令,随机挑选一个英雄),今天总结几个编码过程中常见的随机方法。

以 JavaScript 为例,我们通常会使用 Math 库的 random 方法,获得一个 0 到 1 的随机数。

Math.random()

这里有个概念叫伪随机数,伪随机数的意思就是字面意思,不是真实不可预测的随机,而是按照一定的模拟算法产生的随机,按照这套算法产生的结果是确定的,称为伪随机。

通常 Random 出来的结果不是我们想要的,这时候会做一次数值转换,从给定的范围 0-1 映射到我们的目标范围上。

产品: 今天高兴,给所有用户发个阳光普照红包,金额从 0 到 100w 随机。
Arvit:好的。(傻逼产品)
function valueMapping (x, inMin, inMax, outMin, outMax) {
  return (x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
valueMapping(Math.random(), 0, 1, 0, 100w)

这种平均分配的随机比较常见。但是产品不喜欢这么随便的随机。

产品:我要让 50% 的人抽不中奖,然后抽中三等奖的概率为 30%,抽中二等奖的概率为 15%,抽中一等奖的概率为5%。你能做到吗?
Arvit:看不起我??? 这有难度吗?

简单需求当然要满足,这种抽奖的条件有限,我们可以用有放回地从容器里面取乒乓球的方式来实现。只要往容器里面放入满足比例的小球,比如总共100个球,50个球是不中奖的,那么随机抽取一个,不中奖的概率就是 50%。

let container = [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
var random = container[Math.floor(Math.random() * container.length)]

世界上比女人更善变的,是做产品的女人。

产品:我觉得吧…
Arvit: 我知道了,可以做。
产品:你怎么知道我要说什么?
Arvit:经验。

产品说,之前的随机算法太傻逼了,希望跟资料完整度线性相关,资料完整度高的用户被抽中的概率更高。资料完整度是一个 0 到 1 的数字。

function randomFuck (completingRate) {
  return Math.random() < completingRate
}
产品:那如果是二次相关呢?
Arvit:我的时间很宝贵,你能一次说完吗?(贪玩蓝月在线中…)
function randomFuckTwice (completingRate) {
  return Math.random() * Math.random() < completingRate
}
产品:别人家的阳光普照抽奖曲线好看多了,据说是中值为 100 ,方差 10 的正态分布,我们抄一下?
Arvit: (ノ`Д)ノ滚
import randomNormal from 'random-normal'
randomNormal({mean: 100, dev: 10})

高斯分布做雾气病毒效果:

产品:抽奖就这样吧,不改了
Arvit:Niceeeeeeeee
产品:我们做下一个需求
Arvit:…
产品:我想让小球位置随机变化,要求很简单,下一个随机位置跟上一次相关,而不是瞎几把跳。
Arvit:…

Perlin Noise 是由 Ken Perlin 发明的自然噪声生成算法。PerlinNoise 算法产生出来的前后两个随机数之间有一点的关联,通常用来生成一些纹理效果。
Perlin Noise 演示 Demo:

最近在重新开始看《The Nature Of Code》 这本书,17 年初的时候买入,快速阅读过一遍,收益良多,然而很多知识点都遗漏了,趁着最近换项目组,比较多时间,重新仔细看一遍,巩固学习。

以上。总结的内容都比较简单,但是正如 Arvit 所说,多学一些方法在身上,那么下次面对产品经理需求的时候能更游刃有余,这是我们对外的武器。

相关链接

如需转载,请注明出处: w3ctrain.com / 2018/02/12/random-func-sum-up/

我叫周晓楷

我现在是一名前端开发工程师,在编程的路上我还是个菜鸟,w3ctrain 是我用来记录学习和成长的地方。