c编译器抽卡片
① 抽卡概率与期望指计算
跟一个朋友讨论了抽卡概率和期望的问题,平时也不怎么研究“数学问题”,突然来这么一下,也是有点懵逼。之后搜到了这篇帖子https://bbs.nga.cn/read.php?tid=20203748&rand=359,有了些灵感。有几个数值不知道怎么算出来的,也是探索了一段时间,弄懂之后感觉还是挺简单的。记录一下,给像我一样“愚蠢”的有缘人一些灵感。
朋友的想法是,打造装备,每次成功概率递增,计算打造成功的期望。
以图片1中的数据为例,A列就是强化装备的次数,B列就是某次强化装备时的概率(系统设定的),C列就是某次强化装备时的实际概率(条件概率),D列就是强化次数对应的期望,E列就是强化20次的总期望,也就是按照这种概率,玩家强化装备成功的平均次数为5.29次。
实际概率的算法,比如第二次成功的概率不是10%,因为它的成功建立在第一次的失败上,所以是(1-5%)*10%。同样的第三次成功的概率建立在第一次和第二次都失败的基础上,所以是(1-5%)*(1-10%)*15%。以此类推,根据设定的概率得到20次分别对应的实际概率。
期望的算法,则是 次数*其对应的实际概率。总期望就是对各个次数对应的期望的累加。这种算法一定要保证,所有事件(次数)的实际概率的总和为1。如果不为1,简单的累加就不是真实的期望。这里我一开始没想明白,下面用个例子解释一下。
图片2中的事例和数据是比较好理解的,跟图1中的差不多,只不过图2中的概率是恒定不变的,计算起来容易一点。
需要注意的是,计算S人物中奖期望值里,前99抽的概率*抽数都是一样的,代入公式,第100抽的不一样了。第100抽的概率是(1-0.015)^99,并没有像1到99抽那样乘以0.015,是因为,第100抽必定会出,所以应该是(1-0.015)^99*100%。
其次,平均花费的计算困扰了我很久,也是一开始没想明白的地方。
图3是我用excel模拟的10抽内的数据。因为之前计算100抽的期望就是把各个次数的期望相加,就是M列,但是数据对不上,而且也很不合理。经过多次推敲,终于得到10抽内平均花费是5.735的数据。就是用sum(M1:M10)/sum(K1:K10). 因为,平均抽卡数 = 总抽卡数/总人数。
如果总人数是1的话,前10抽的人数就是1*14.027%。K列代表的是实际概率,可以理解为其对应的抽卡次数对应的人数概率。比如,有0.015的玩家抽了1次就抽到了。有0.014775的玩家抽了2次抽到了。所以 0.015*1得到人数,1得到抽卡次数,0.015*1*1得到,这0.015的人抽了几张卡。 0.01477*1得到人数,1得到抽卡次数,0.01477*1*2得到,这0.01477的人抽了几张卡。以此类推。所以,M这列的总和,代表的是,前10抽抽到卡的这些人抽卡的总数。然后总抽卡数/总人数=0.754/0.1402 = 5.375。剩下的几个平均花费也是这么算。图二中46抽内的平均花费应该是算错了的。
② c语言这么厉害,它自身又是用什么语言写的编写过程被称为自举
来自一个小白的提问: “C语言本身用什么语言写的?”
换个角度来问,其实是:C语言在运行之前,得编译才行,那C语言的编译器从哪里来?用什么语言来写的?如果是用C语言本身来写的,到底是先有蛋还是先有鸡?
我们假设世界上不存在任何编译器, 先从机器语言说起,看看怎么办。
机器语言可以直接被CPU执行,不需要编译器。
然后是汇编语言, 汇编语言虽然只是机器语言的助记符,但是也需要编译成机器语言才能执行,没办法只能用机器语言来写这第一个编译器了(以后就不用了)。
汇编语言的问题解决了,就往前迈进了一大步,这时候就可以用汇编语言去写C语言的编译器,我们说这是C编译器的老祖宗。
有了这个老祖宗,就可以编译任意的C语言程序了,那是不是可以用C语言本身写一个编译器?只要用老祖宗编译一下就可以了。
OK, 这么一层层上来,终于得到了一个用C语言写的编译器, 真是够麻烦的。
到这个时候,之前那个汇编写的C语言编译器就可以抛弃了。
当然,如果在C语言之前,已经出现了别的高级语言,例如Pascal,那就可以用Pascal来写一个C语言的编译器。
第一个Pascal的编译器据说使用Fortran写的。而作为第一个高级语言的Fortran,它的编译器应该是汇编语言写的。
关于编译器,这里边有个有趣的传说:
传说Unix 发明人之一的 Ken Thompson在贝尔实验室,大摇大摆的走到任何一台Unix机器前,输入自己的用户名和密码,就能以root的方式登录!
贝尔实验室人才济济,另外一些大牛发誓要把这个漏洞找出来,他们通读了Unix的C源码,终于找到了登录的后门, 清理后门以后编译Unix , 运行, 可是Thompson 还是能够登录进去。
有人觉得可能是编译器中有问题,在编译Unix的时候植入了后门, 于是他们又用C语言重新写了一个编译器,用新的编译器再次编译了Unix, 这下总算天下太平了吧。
可是仍然不管用, Thompson 依然可以用root登录,真是让人崩溃!
后来Thompson 本人解开了秘密,是第一个C 语言编译器有问题, 这个编译器在编译Unix源码的时候,当然会植入后门, 这还不够,更牛的是,如果你用C 语言写了一个新编译器,肯定也需要编译成二进制代码啊,用什么来编译,只有用Thompson写的那第一个编译器来编译,好了, 你写的这个编译器就会被污染了,你的编译器再去编译Unix , 也会植入后门 :-)
说到这里我就想起了几年前的XcodeGhost 事件,简单来说就是在Xcode(非官方渠道下载的)中植入了木马,这样XCode编译出的ios app都被污染了,这些app就可以被黑客利用做非法之事。
虽然这个XCodeGhost和Thompson的后面相比差得远,但是提醒我们,下载软件的时候要走正规渠道,从官方网站下载,认准网站的HTTPS标准,甚至可以验证一下checksum。
可能有人问:我用汇编写一段Hello World都很麻烦,居然有人可以用它写复杂的编译器?这可能吗?
当然可能,在开发第一代Unix的时候,连C语言都没有, Ken Thompson 和 Dennis Ritchie 可是用汇编一行行把Unix敲出来的。 WPS第一版是求伯君用汇编写出来的, Turbo Pascal 的编译器也是Anders 用汇编写出来的,大神们的能力不是普通人能想象得到的。
对于编译器来说,还可以采用“滚雪球”的方式来开发:
还是以C语言为例,第一个版本可以先选择C语言的一个子集,例如只支持基本的数据类型,流程控制语句,函数调用...... 我们把这个子集称为C0。
然后用汇编语言写个编译器,只搞定这个语言的子集C0,这样写起来就容易不少。
C0这个语言可以工作了,然后我们扩展这个子集,例如添加struct,指针...... ,把新的语言称为C1。
那C1这个语言的编译器由谁来写? 自然是C0。
等到C1可以工作了,再次扩展语言特性,用C1写编译器,得到C2。
然后是C3, C4...... 最后得到完整的C语言。
这个过程被称为bootstraping , 中文叫做自举。
对于热爱编程的人来说,有一群一起学习一起解答的小伙伴很重要!
这里有一个 C/C++编程学习交流俱乐部 (群),私信我【01】进入!
还有编程学习文件(源码,零基础教程,项目实战教学视频),欢迎初学者和正在进阶中的小伙伴们!
③ c语言编译器是一种什么
c语言编译器是一闹樱种软件系统。
C语言是一种结构化语言。它层次清晰,便于按模块化方式组织程序,易于调试和维护。C语言的表现能力和处理能力极强。它不仅具有丰富的运算符和数据类型,便于实现各类复杂的数据结构。它还可以直接访问内存的物理地址,进行位(bit)一级的操作。
早期的C语言主要是用于UNIX系统。由于C语言的强大功能和各方面的优点逐渐为人们认识,到了八十年代,C开始进入其它操作系统,并很快在各类大、中颤弯返、小和微茄饥型计算机上得到了广泛的使用。成为当代最优秀的程序设计语言之一。
④ 全国计算机等级考试二级C语言的考试题目都是从《C语言题库》里面抽取的题目吗
全国计算机等级考试二级C语言的考试题目的小题不是从《C语言题库》中抽取的,后面的大题即编程题全部是从最近的一年的《C语言题库》中抽取的。考题大部分是C语言,少部分是算法与数据结构里面的东西。就算不是《C语言题库》题库里的题,但是题型都差不多的。
c语言是一门面向过程、抽象化的通用程序设计语言,广泛应用于底层开发。C语言具有高效、灵活、功能丰富、表达力强和较高的可移植性等特点,在程序设计中备受青睐。C语言编译器普遍存在于各种不同的操作系统中,例如Microsoft Windows、macOS、Linux、Unix等。C语言的设计影响了众多后来的编程语言,例如C++、Objective-C、Java、C#等。