漫画:给女朋友解释为什么随机播放歌曲并不随机
本文经授权转载自漫话编程(ID:mhcoding)
2019程序员转型学什么?
https://edu.csdn.net/topic/ai30?utm_source=csdn_bw
周末,开车带女朋友出去玩,车里面,随机播放着周杰伦的歌曲。我正沉浸在『得儿飘,得儿飘,得儿意的飘』中,幻想着自己是秋名山车神,突然,旁边的女朋友说话了。
诶,你车上的歌曲是随机播放的吗?为什么听来听去反反复复都是那么几首歌在重复?
嗯,音乐随机播放用的是伪随机算法呗。
伪随机性是一个过程似乎是随机的,但实际上并不是。伪随机数是看似随机实质是固定的周期性序列,也就是有规则的随机。
什么是随机数
随机数在计算机应用中使用的比较广泛,最为熟知的便是在密码学中的应用。随机数有3个特性,具体如下:
随机性:不存在统计学偏差,是完全杂乱的数列
不可预测性:不能从过去的数列推测出下一个出现的数
不可重现性:除非将数列本身保存下来,否则不能重现相同的数列
音乐播放器的随机播放如何实现的
现在的音乐播放器都比较智能了,都带有一些类似于歌曲推荐的功能,会给听众随机推荐歌曲,这种是基于用户听歌习惯的随机推荐,不在我们讨论的范围内。我们只讨论那种简单的,比如使用简单的播放器随机播放一个CD卡中的列表的情况。
常见的音乐随机播放算法有两种,分别是Random算法和Shuffle算法。
Random算法
Random算法相对比较简单,播放当前歌曲时才随机生成下一曲。
Random算法是在选取即将播放的歌曲时,进行一个随机数的运算,得到即将播放的歌曲在播放列表中的索引,播放列表本身并没有被打乱,只是利用随机函数从播放列表中选取一首歌曲进行播放而已。
可以使用Java语言实现这种Random随机数算法:
Calendar ca = Calendar.getInstance();//获取系统当前时间
int i;
Random rand =new Random(ca.get(Calendar.MINUTE)*ca.get(Calendar.SECOND));//将随机数的种子设置为当前系统时间的分*秒
i=rand.nextInt(maxnum);//maxnum是随机数最大不超过得值
Random算法另一个缺陷是当点击“上一曲”时,跟“下一曲”功能完全一样,都是重新生成随机数,并利用它从播放列表中选取歌曲进行播放,而不会回到刚刚播放的那一首歌。
这种方法不好,都没办法找到上一首了。
其实也有解决办法,比如提供个历史纪录来弥补。
太麻烦了吧。还有另外的算法吗?
有的,那就是洗牌算法。
Shuffle算法
Shuffle算法和排序算法正好相反,是从有序到乱序的一个过程,俗称洗牌算法。
它将播放列表中的歌曲顺序打乱,变成一个和原来歌曲顺序没有任何关系的乱序的播放列表,之后进行歌曲的播放,并支持当用户点击“上一首”时,能够回到刚刚播放的那一首歌曲。
这种算法相对于Random算法来说,并不是完全意义上的随机,只不过是对歌曲列表的乱序而已,歌曲的播放顺序还是相对固定的。
在Java中,有现成的shuffle算法实现,即Collections类中的两个重载的shuffle方法:
public static void shuffle(List<?> list) {Random rnd = r;if (rnd == null)r = rnd = new Random();shuffle(list, rnd);
}
private static Random r;public static void shuffle(List<?> list, Random rnd) {int size = list.size();if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {for (int i=size; i>1; i--)swap(list, i-1, rnd.nextInt(i));} else {Object arr[] = list.toArray();// Shuffle arrayfor (int i=size; i>1; i--)swap(arr, i-1, rnd.nextInt(i));// Dump array back into listListIterator it = list.listIterator();for (int i=0; i<arr.length; i++) {it.next();it.set(arr[i]);}}
}
哦,那我们的播放器应该是使用Shuffle实现的吧。
嗯,我们每次听的歌曲顺序几乎都一致,表现上比较像。
那我们这个就是伪随机,如果使用Random就是真随机了。
不是的。这是不同的概念。
真随机与伪随机
随机数分为真随机数和伪随机数,我们程序使用的基本都是伪随机数,其中伪随机又分为强伪随机数和弱伪随机数。
真随机数,通过物理实验得出,比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等。需要满足随机性、不可预测性、不可重现性。
伪随机数,通过一定算法和种子得出。软件实现的是伪随机数。
强伪随机数,难以预测的随机数。需要满足随机性和不可预测性。
弱伪随机数,易于预测的随机数。需要满足随机性。
上面介绍Random算法和Shuffle算法的时候,代码实现都是伪随机算法。可以这样说:
只要这个随机数是由确定算法生成的,那就是伪随机。只能通过不断算法优化,使你的随机数更接近随机。
有限状态机不能产生真正的随机数的,所以,现代计算机中,无法通过一个纯算法来生成真正的随机数,无论是哪种语言,单纯的算法生成的数字都是伪随机数,都是由可确定的函数通过一个种子,产生的伪随机数。
这也就意味着,如果知道了种子,就可以推断接下来的随机数序列的信息。这就有了可预测性。
那么真随机数怎么产生的呢?
通过真实随机事件取得的随机数才是真随机数。
真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等。这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高,效率低。
现有的真随机数生成器,比如PuTTYgen的随机数是让用户移动鼠标达到一定的长度,之后把鼠标的运动轨迹转化为种子;Intel通过电阻和振荡器来生成热噪声作为信息熵资源;Unix/Linux的dev/random和/dev/urandom采用硬件噪音生成随机数;
所以,要想生成真的随机数,是无法用任何一个纯算法实现的。都需要借助外部物理现象。
啊?这也太难了吧,想要生成个随机数,竟然还要懂物理学。
是的。确定性的算法生成的随机数,至少都有可重现性。那就不是真随机数了。
那你们平时工作重要使用随机数怎么办啊?
这就要看场景了,一般使用伪随机数就可以解决问题了。
Java中的随机数生成器
Java语言提供了几种随机数生成器,如前面提到的Random类,还有SecureRandom类。
伪随机数生成器
伪随机数发生器采用特定的算法,将随机数种子seed转换成一系列的伪随机数。伪随机数依赖于seed的值,给定相同的seed值总是生成相同的随机数。伪随机数的生成过程只依赖CPU,不依赖任何外部设备,生成速度快,不会阻塞。
Java提供的伪随机数发生器有java.util.Random类和
java.util.concurrent.ThreadLocalRandom类。
Random类采用AtomicLong实现,保证多线程的线程安全性,但正如该类注释上说明的,多线程并发获取随机数时性能较差。
多线程环境中可以使用ThreadLocalRandom作为随机数发生器,ThreadLocalRandom采用了线程局部变量来改善性能,这样就可以使用long而不是AtomicLong,此外,ThreadLocalRandom还进行了字节填充,以避免伪共享。
强随机数发生器
强随机数发生器依赖于操作系统底层提供的随机事件。强随机数生成器的初始化速度和生成速度都较慢,而且由于需要一定的熵累积才能生成足够强度的随机数,所以可能会造成阻塞。熵累积通常来源于多个随机事件源,如敲击键盘的时间间隔,移动鼠标的距离与间隔,特定中断的时间间隔等。所以,只有在需要生成加密性强的随机数据的时候才用它。
Java提供的强随机数发生器是java.security.SecureRandom类,该类也是一个线程安全类,使用synchronize方法保证线程安全,但jdk并没有做出承诺在将来改变SecureRandom的线程安全性。因此,同Random一样,在高并发的多线程环境中可能会有性能问题。
在linux的实现中,可以使用/dev/random和/dev/urandom作为随机事件源。由于/dev/random是堵塞的,在读取随机数的时候,当熵池值为空的时候会堵塞影响性能,尤其是系统大并发的生成随机数的时候。
真随机数发生器
在Linux系统中,SecureRandom的实现借助了/dev/random和/dev/urandom,可以使用硬件噪音生成随机数;
http://random.org/,从1998年开始提供在线真随机数服务了,它用大气噪音生成真随机数。他也提供了Java工具类,可以拿来使用。地址:https://sourceforge.net/projects/randomjapi/
奥,我好像懂了:真随机数生成要求太高了,所以一般都是用伪随机数。
是这样子的。
可是,虽然我理解了,但是我还是希望歌曲的随机可以真随机怎么办呢?
为了躲避这个看(wu)似(li)合(qu)理(nao)的问题,我拉着她回到车子,找了一首她最喜欢的《演员》单曲循环了。
【完】
热
全面学python的时代,作为程序员你怎么看?
https://edu.csdn.net/topic/python115?utm_source=csdn_bw
文 推 荐
☞ 光凭 5G 根本无法解决宽带问题!
☞ 爬取 4400 条淘宝洗发水数据,拯救你的发际线!(附代码和数据集)
☞ 如今,你感受到内存技术的“思维速度”了吗?
☞ 程序员写代码没激情该怎么破?
☞ 跨界打击, 23秒绝杀700智能合约! 41岁遗传学博士研究一年,给谷歌祭出秘密杀器!
☞ 90后美女学霸传奇人生:出身清华姚班,成斯坦福AI实验室负责人高徒
☞ 神操作!这段代码让程序员躺赚200万?给力!
print_r('点个好看吧!');
var_dump('点个好看吧!');
NSLog(@"点个好看吧!");
System.out.println("点个好看吧!");
console.log("点个好看吧!");
print("点个好看吧!");
printf("点个好看吧!\n");
cout << "点个好看吧!" << endl;
Console.WriteLine("点个好看吧!");
fmt.Println("点个好看吧!");
Response.Write("点个好看吧!");
alert("点个好看吧!")
echo "点个好看吧!"
喜欢就点击“好看”吧!
漫画:给女朋友解释为什么随机播放歌曲并不随机相关推荐
- php 随机播放音乐,听音乐时随机播放真的是随机的吗?
听音乐时随机播放真的是随机的吗? 一只学霸 (ID:bajie203) 说到随机播放 前段时间我不是为了你们 在听禁曲嘛 好家伙接连几天睡觉的时候听歌 都给我放禁曲 你们根本不懂 那是种什么感觉 我差 ...
- QQ音乐的随机播放 是真的随机吗?
其实我早就怀疑 这个随机播放不像是随机啊,因为我自己经常躺在床上随机听歌,但是有些歌经常随到,但是有些歌老是听不到. 所以今天刚好也无聊,就拿自己的歌单做个测试. 首先我把自己的一个歌单拷出来: 歌单 ...
- ipad iphone开发_如何在iPhone或iPad上随机播放或重复播放歌曲
ipad iphone开发 You can add variety to your music listening experience on iPhone and iPad by turning o ...
- Arduino按键控制MP3模块随机播放音乐(YX5300 MP3音乐模块)
设计者:STCode (公众号同名) 1)功能描述 这个设计主要是通过按键来控制播放音乐,主要涉及到的内容有按键和YX5300 MP3音乐模块的使用,通过按压按键来达到随机播放音乐曲目的目的. 2)使 ...
- 当你按下「随机播放」时,QQ音乐和网易云们都做了什么?
以下内容转载自 https://zhuanlan.zhihu.com/p/303256600 在音乐类应用中,随机播放应该是我们最常用的功能之一.而作为产品经理而言,大家有没有想过:随机播放的算法应该 ...
- 漫画:如何给女朋友解释灭霸的响指并不是真随机消灭半数宇宙人口的?
本文经授权转载自漫话编程(ID:mhcoding) 周末,陪女朋友去电影院看了<复仇者联盟4:终局之战>,作为一个漫威粉三个小时看的是意犹未尽.出来之后,准备和女朋友聊一聊漫威这十年. 在 ...
- 漫画:如何给女朋友解释灭霸的指响并不是真随机消灭半数宇宙人口的?
本文经授权转载自漫话编程(ID:mhcoding) 周末,陪女朋友去电影院看了<复仇者联盟4:终局之战>,作为一个漫威粉三个小时看的是意犹未尽.出来之后,准备和女朋友聊一聊漫威这十年. 在 ...
- android 小型音乐播放器(实现播放、下一首、上一首、自动播放、随机播放按钮、当前播放歌曲界面)
该文章主要针对 android 的音乐播放器软件进行简单的功能添加:播放.断点播放.停止.上一曲.下一曲.随机播放.显示当前播放歌曲(后续会为当前显示的播放添加动画): 软件开发流程: 1.先向内存卡 ...
- 音乐播放器的实现(四)—— 歌曲列表、顺序播放、单曲循环、随机播放、自动下一曲
音乐播放器的实现(四)-- 歌曲列表.顺序播放.单曲循环.随机播放.自动下一曲 传送门:(完整工程见第五章篇尾) 音乐播放器的实现(一)-- Audio Listener和Audio Source面板 ...
最新文章
- 不吹牛,中国车主已经实现了「停车自由」
- linux kvm usb设备,KVM客户机使用主机USB设备
- 北京高性能计算机应用中心,中国气象局高性能计算机系统资源使用报告-北京高性能计算机应用中心.PDF...
- 论文浅尝 | 用于学习知识图谱嵌入的一种基于注意力机制的新型异构 GNN 框架HRAN...
- [转载] 列表、元组及通用序列操作
- 手写基础排序及查找算法
- matlab ds18b20 单片机,基于51单片机ds18b20温度检测————设计报告.doc
- yv12转nv12,nv12转I420
- 权限管理系统之字典(代码)管理
- Node.js:中间件——配置静态资源中间件
- 信息熵、互信息、KL散度
- 微型计算机原理与接口技术马静答案,微机原理与接口技术(马静)
- 二维绕任意点旋转_旋转变换(一)旋转矩阵
- Delphi著名皮肤控件库大全
- [译]const T vs. T const ——Dan Saks 【翻译】
- 自定义UDF函数和UDTF函数
- 中国学生常见的英文论文写作问题
- Vanish CDN
- 外网访问内网的FTP服务器
- JavaScript读书笔记四
热门文章
- 华为vrrp默认优先级_华为vrrp配置
- proxytable代理不生效_深圳劳动纠纷律师为你解答劳动合同没有盖章是否生效
- python中for循环和while循环的区别_Python中for循环语句和while循环语句有何不同
- 如何判断两物体加速度相等_力学实验2:探究加速度和力的关系
- Qt的QThread多线程使用
- Flutter实战一Flutter聊天应用(九)
- 前端开发者必备google插件
- SQL注入学习part07:(SQL注入语句总结)
- Java 拷贝,你能说出个 123 么?
- 深度解析 | 用 AI 帮助听障人群,一共需要几步?