程序员的数学课08 加乘法则:如何计算复杂事件发生的概率?

news/2024/5/8 5:05:36/文章来源:https://blog.csdn.net/fegus/article/details/127116921

在我们的工作和生活中少不了对概率的计算,对概率的准确计算会帮助我们做出更加合理高效的决策。

例如,早上出门之前,你需要对是否携带雨伞进行决策。如果没有任何依据而随机决策,那么就会遇到下雨没带伞或者晴天带伞的麻烦;而如果有依据,你知道今天下雨的概率超过 80%,那么你就会做出带雨伞的决策,来规避下雨带来不便的风险。

那么问题来了,对于一个事件而言,其发生的概率该如何计算呢?这一讲我们就来解答。

概率来自统计

还记得我们最开始接触概率时的定义吗?概率用来描述一个事件发生的可能性,它是个 0 到 1 的数字。概率的定义式就是 m/n,含义为假设某个现象重复执行 n 次(n 较大),其中目标事件发生了 m 次,则目标事件发生的概率就是 m/n。

举个例子,一枚硬币重复抛 100 次,其中正面朝上 49 次,反面朝上 51 次,则硬币正面朝上的概率就是 0.49。

概率的定义式非常重要,如果你能灵活运用,并结合一定的代码开发,有时候可以快速解决一个复杂的数学问题。

我们举个例子,在一个正方形内有一个内切圆,在正方形内随机选取一点,问该点也在圆内的概率是多少?
Lark20201117-165117.png
这是个数学问题,但你可以借助概率的定义式完成计算,代码如下:

import random
def main():m = 0n = 1000for _ in range(n):x = random.random()y = random.random()if x*x + y*y < 1:m += 1print 1.0*m/n
if __name__ == '__main__':main()

我们对代码进行走读:

  • 第 4、5 行定义了 m 和 n 两个变量。其中,n 赋值为 1000,意味着我们要重复执行这个动作 1000 次,m 表示坐标点落入圆内的次数;

  • 接下来,就是第 6~10 行的 1000 次实验的循环了。每次实验,我们随机生成一个坐标点 (x,y),其中 x 和 y 的取值范围都是 0~1 的浮点数;

  • 这样,在第 9 行中,如果点 (x,y) 与原点的距离小于 1,则表示该点在圆内,m 自动加 1;

  • 最后,打印出 m 和 n 的比值。

我们运行程序的结果如下:
Drawing 1.png

这个题目如果从数学的视角来计算,结果就是 P =πr2÷4r2= π÷4 = 0.785,这与我们的计算结果是一样的。

未来,如果你遇到复杂的概率计算时,不妨试着用这种统计法来求解。

用加乘法则来计算复杂事件的概率

统计法是一种用程序思想解决数学问题的范例,但这并不意味着你不需要学习数学中概率计算的原理。原因在于,有些场景下重复试验的条件并不成立;或者是事件极其复杂,重复试验的代价太大。这就需要我们掌握一些基本的概率计算法则。

在这一课时,我们重点介绍加法原理和乘法原理。

1.加法原理

加法原理可以理解为,一个事件有多个可能的发生路径,那么这个事件发生的概率,就是所有路径发生的概率之和。

例如,在掷骰子的游戏中,掷出的点数大于 4 的概率是多少?

掷骰子的 6 个可能的点数是 6 个路径,每个路径发生的概率是 1/6,其中满足条件中点数大于 4 的只有最后两条路径。利用加法原理则有,点数大于 4 的概率为 1/6 + 1/6 = 1/3,如下图:
Lark20201117-165123.png

2.乘法原理

如果将加法原理理解为是串行的逻辑,那么乘法原理就是个并行的逻辑。乘法原理可以理解为,某个事件的发生,依赖多个事件的同时发生。那么原事件发生的概率,就是所有这必须发生的多个事件的乘积。

例如,你与大迷糊一起玩掷骰子的游戏,求大迷糊掷出 4 点的同时,你最终获胜的概率是多少?

这时候,计算的概率就必须两个条件同时发生。这两个条件分别是,大迷糊掷出 4 点和你的点数大于 4。根据前面的计算,我们知道掷骰子点数大于 4 的概率为 1/3。因此,这两个条件发生概率的乘积就是最终的结果,即 P (大迷糊掷出 4 点的同时,你最终获胜) = 1/6×1/3 = 1/18 = 0.0556。

对于这个例子,我们可以用统计法进行仿真,代码如下:

import random
obj = 0.0
for _ in range(10000):	you = random.randint(1,6)damihu = random.randint(1,6)if damihu == 4 and you > damihu:obj += 1
print obj/10000

我们对代码进行走读:

  • 第 3 行的 obj,就是最终事件发生的频次;

  • 我们对现象观察 10000 次,这样就形成了第 4~8 行的 for 循环;

  • 每次循环,在第 5 和 6 行,随机生成你的点数和大迷糊的点数;

  • 第 7 行进行判断,大迷糊为 4 点且你的点数大于大迷糊的点数;

  • 如果满足条件,则在第 8 行执行 obj 加 1;

  • 最终,打印出 obj 除以 10000。

这段代码运行的结果如下图,跟我们计算的结果几乎一致。
Lark20201117-165125.png

条件概率

刚刚的加乘法则,适用于独立事件的概率求解。独立事件的含义,就是上面所提到的原子事件。也就是,拆解出的子事件之间没有任何的先后或互相影响结果的因素。例如,大迷糊爱喝咖啡,和大漂亮爱穿高跟鞋,就是两个毫无关系的独立事件。对于独立事件,应用加乘法则可以很快得到整体的概率。

那么,如果我们无法得到独立的事件,而都是耦合在一起的事件,又该如何计算概率呢?这就需要用到条件概率的知识了。

条件概率,指事件 A 在另外一个事件 B 已经发生条件下的发生概率,记作 P(A|B),读作“B 条件下 A 的概率”。条件概率的定义式为 P(A|B) = P(AB) / P(B),将其变换一下就是 P(AB) = P(A|B) × P(B)。

条件概率的特殊性,在于事件 A 和事件 B 有千丝万缕的联系。如果二者为毫无关联的独立事件的话,事件 A 的发生则与 B 毫无关系,则有 P(A|B) = P(A)。

我们给一个例子辅助理解。假设有一对夫妻,他们有两个孩子。求他们在有女儿的条件下,两个孩子性别相同的概率是多少?

这个概率看似难求,但只要定义好事件并套用定义式,就能完成计算。我们把事件 B 定义为,这对夫妻有女儿,事件 A 为两个孩子性别相同。因此,计算的目标就是 P(A|B),也就是计算 P(A|B) = P(AB) / P(B)。

  • 事件 AB 的含义是这对夫妻有女儿,且两个孩子性别相同。也就是说,这对夫妻的孩子都是女儿,即第一胎是女儿,第二胎还是女儿。此时根据乘法原理,得到 P(AB) = (1/2)×(1/2) = 1/4。

  • 事件 B 为这对夫妻有女儿,不管第几胎,甚至是两胎都是女儿。这样就有了 3 种可能的情况:分别是第一胎女儿、第二胎儿子;第一胎儿子、第二胎女儿;第一胎女儿、第二胎女儿。这样根据加法原理和乘法原理,得到 P(B) = (1/2)×(1/2)+(1/2)×(1/2)+(1/2)×(1/2) = 3/4。因此 P(A|B) = P(AB) / P(B) = (1/4) / (3/4) = 1/3。

对于这个例子,我们用如下代码进行仿真:

import random
fenzi = 0
fenmu = 0
for _ in range(1000):#0 is girl; 1 is boyfirst = random.randint(0,1)second = random.randint(0,1)if first == 1 and second == 1:continueelse:fenmu += 1if first == second:fenzi += 1
print 1.0*fenzi/fenmu

我们对代码进行走读。

  • 第 6 行开始,重复循环 1000 次。

  • 第 8~9 行,随机生成两个孩子的性别。用 0 代表女儿,用 1 代表儿子。如果两个孩子都是儿子,则进行下一轮迭代。因为,这并不满足至少有一个女儿的假设条件。

  • 第 12 行开始,如果有女儿,则分母加 1,如果两个孩子的性别一致,则分子也加 1。

  • 最终打印出分子和分母的比值。

程序执行的效果如下图所示,结果与我们计算的近似相等:
Lark20201117-165128.png
当你遇到一个复杂事件的时候,一定要通过串行或并行的两重逻辑进行拆解。再基于加乘法则,利用每个原子粒度事件的概率,合成最终复杂事件发生的概率。

接下来,我们看一些更复杂的问题。

一个概率计算的案例

假设大漂亮在某电商公司,负责实时的红包券投放策略。大漂亮设计的投放策略是,如果用户在商品的详情页停留了 1 分钟以上,则认为该用户正在纠结是否购买此商品。此时,给用户实时投放一定金额的红包,来增加用户的购买可能性。

试着分析一下,这里的事件之间的概率关系,以及投放红包到底产生了怎样的概率刺激效果?

可以想象,用户购买某个商品的动作顺序是,点击商品详情页,再付款购买。很显然“点击详情页”和“付款购买”并不是独立的事件,原因在于不点击详情页是无法完成购买动作的,二者存在先后关系。因此 P(点击并购买) = P(购买|点击) × P(点击),这个公式对所有的用户都生效。

接下来,大漂亮的红包投放条件是,用户在商品的详情页停留了 1 分钟以上。此时,产生购买行为的用户就有两部分,分别是使用红包的购买用户和未使用红包的购买用户。很显然,使用红包和不使用红包是两个并行的逻辑,可以采用加法原理进行概率计算,因此有

P(点击并购买) = P(点击并使用红包购买) + P(点击并未使用红包购买)

再分别拆解两部分概率,根据乘法原理和条件概率,则有

P(点击并购买) = P(购买|点击并获得红包) × P(获得红包|点击) × P(点击) + P(购买|点击并未获得红包) × P(未获得红包|点击) × P(点击)

假设策略上线后,大漂亮根据上线前后的数据,统计得到了每个环节的概率如下表所示:

Lark20201117-165130.png

从表中数据可以发现以下几个结论:

  • 投放红包是在点击之后,因此对点击率无影响;

  • 用户点击商品详情页的条件下,获得红包的概率是 0.3,未获得红包的概率是 0.7;

  • 对于未获得红包的用户,其购买率与实验前一致,都是 0.4。对于获得红包的用户,其购买率会上升,达到 0.5。

最终,根据公式计算下来,点击并购买的概率由 0.2 提升到了 0.215,这就是红包投放的收益。

小结

最后,我们对这一讲进行总结。概率的计算是高中和大学数学中有趣又让人头疼的内容,为了学好概率的知识,你不妨牢牢记住下面几个关键点。

  • 概率来自统计。当你束手无策时,不妨从多次的重复试验中,统计目标事件出现的频次,来估算概率。

  • 加乘法则是计算概率的有力手腕。对复杂事件按照并行或串行来拆解,再利用加乘法则就可以完成复杂事件的概率计算。

  • 条件概率是处理有关联事件的方法。虽然条件概率有些晦涩,但牢牢记住定义式 P(A|B) = P(AB) / P(B),就能让条件概率转换为普通事件的概率。在实际应用中,一定要耐着性子,仔细琢磨事件背后的相关关系,再利用这些方法,就能把概率计算清楚。

最后,我们给出一个思考题:一根绳子随机切成 3 段,问能组成三角形的概率是多少?这个问题至少有 3 种可行办法。我们会在后续的课程中公布答案,不妨先自己来试试看吧。


精选评论

*阳:

0.25,公式,统计法。只能想到两种

    讲师回复:

    结果正确。统计法很好,是程序员解题的通用方法。另外,可以从数学角度来找两个方法:第一个,可以把切3段,拆解为3个事件,增加三角形两边成立的不等式约束,可以推导出概率;也就是你说的公式法。最后一个方法是一种通过画图,计算可行区域面积的方法。这个方法比较冷门,不是很容易想到,可以参考这个链接:https://blog.csdn.net/fanoluo/article/details/40374571?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control。

**安:

这道题好像还涉及两种情况:1.事先找好两个切分点,2.先切一段x,再从剩下的切出y 和z

    讲师回复:

    这也是一种计算方法。从所有可选的切分点中计算出合法的切分点,二者的比例就是结果。

*鹏:

啊,我只想到两个方法:1.计算机模拟;2.公式推导.

    讲师回复:

    计算机模拟是一个办法。公式推导应该不止1种方法。还可以试着从一种类似于线性规划的方法,网上有这个题的答案。我也会在后续内容中给出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_16577.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SiO2/PAA/Ag复合纳米粒/酞菁修饰磁性温敏二氧化硅纳米微球/中空SiO2/TiO2纳米微球的制备

小编给大家分享了SiO2/PAA/Ag复合纳米粒/酞菁修饰磁性温敏二氧化硅纳米微球/中空SiO2/TiO2纳米微球的制备与研究&#xff0c;一起来看&#xff01; SiO2/PAA/Ag复合纳米粒子的制备步骤&#xff1a; 利用溶胶-凝胶法合成胶体二氧化硅微球,用甲基丙烯酰氧丙基三甲氧基硅烷(γ-MP…

业务开发流程

0.摘要 此文主要介绍了业务开发的整体流程、关键节点和需要注意的事项&#xff0c;适用于刚入行的小白&#xff0c;以及对自己过往经验的一个总结整理。持续更新中~~ 1.开发的主要流程&名词释义 大概给大家梳理下一个项目从发起到上线的流程。 ○ 参与人员&#xff1a;业…

redis之为什么那么快

写在前面 在面试中关于redis经常被问到一个问题就是redis为什么快&#xff0c;本文就一起从其底层的数据结构实现来分析下&#xff0c;为什么快&#xff0c;哪些快&#xff0c;哪些慢&#xff0c;哪些操作会导致慢等&#xff0c;下面我们就开始吧&#xff01; 1&#xff1a;为…

【无标题】近几年攻防演练攻击队典型突破的例子

蓝队经典攻击实例 实战攻防演练中红队网络的部署情况各有特点&#xff0c;蓝队也会根据攻 击目标的不同而采取不同的攻击策略和手段。下面几个案例展示的就 是针对红队网络的不同薄弱点采取的不同的典型攻击策略与方法手 段。 正面突破&#xff1a;跨网段控制工控设备 某企业…

C#面向对象程序设计课程实验一:实验名称:C#语言基础、程序流程控制

C#面向对象程序设计课程实验一&#xff1a;实验名称&#xff1a;C#语言基础、程序流程控制实验内容&#xff1a;C#语言基础、程序流程控制一、 实验目的二、实验环境三、实验内容四、实验总结实验内容&#xff1a;C#语言基础、程序流程控制 一、 实验目的 (1)练习 C#变量声明和…

simulink-自定义模块GUI回调函数

目录 一、创建simulink模块 二、自定义GUI步骤 2.1 设计组件界面信息 2.2 GUI控件介绍 2.2.1 Parameter参数配置组件 2.2.2 Container参数配置组件 2.2.3 Display参数配置组件 2.2.4 Action参数配置组件 2.3 控件回调函数使用方法 三、设置Help信息 四、获取配置控件参数 4.…

ubuntu 搭建RKNN-Toolkit环境

1. github下载官方的RKNN-Toolkit项目包 地址&#xff1a;https://github.com/rockchip-linux/rknn-toolkit 然后还需要下载rknn-toolkit包&#xff0c;GitHub下方有链接&#xff1a; 各种版本的官方下载&#xff1a; https://github.com/rockchip-linux/rknn-toolkit/relea…

实现有效控制项目进度,需要做好这些工作

制定出切合的项目计划是执行的重要基础&#xff0c;计划制定的过程同时也是计划逐步细化的过程&#xff0c; 进度计划的贯彻是计划实施的第一步&#xff0c;也是最关键的一步。 一、实现有效控制项目进度&#xff0c;需要做好以下工作&#xff1a; 项目计划&#xff0c;决定…

JavaScript · 9:数据类型转换 隐式转换

总览 1.数据转换为string类型 2.数据转换为Number数字类型 3.数据转换为boolean类型 一、将数据转换为string类型 1.方法 最常用的是“加号拼接字符串”&#xff0c;也就是 隐式转换 &#xff0c;其中用于拼接的字符串内容可以为空 二、将数据转换为number数值类型 1.方…

Vue 响应式实现原理深入浅出

前言 vue 是一个易上手的框架&#xff0c;许多便捷功能都在其内部做了集成&#xff0c;其中最有区别性的功能就是其潜藏于底层的响应式系统。组件状态都是响应式的 JavaScript 对象。当更改它们时&#xff0c;视图会随即更新&#xff0c;这让状态管理更加简单直观。那么&#…

既要又要的正则匹配规则

目录 1 背景 2 浅谈 3 分析 3.1 如何识别成整体块&#xff1f; 3.1.1 正则匹配整体块 3.1.2 “ - ”开头“ - ”结尾 3.1.3 模糊匹配不行&#xff0c;采取精准匹配 3.2 如何作为整体块显示&#xff1f; 3.3 光标不可以中间插入 4 效果展示 5 参考代码 1 背景 在上面…

BorderDet:Border Feature for Dense ObjectDetection

原文链接&#xff1a; 概述 密集物体检测依赖于滑动窗口&#xff0c;在图像的规则网格上预测物体&#xff0c;使用点的特征图来生成预测边界框&#xff0c;但由于边界信息不明确导致无法进行准确定位。本文提出了“Border-Align”的操作来从边界点中提取特征来增强点特征。基于…

Jmeter初始学习

Jmeter是一款优秀的开源性能工具&#xff0c;官网文档地址&#xff1a;http://jmeter.apache.org/usermanual/index.html 一、优点 1.开源工具&#xff0c;可扩展性非常好&#xff1b; 2.高可扩展性&#xff0c;用户可自定义调式相关模块代码&#xff1b; 3.精心简单的GUI设…

iOS App更换图标Logo(本地更换)

1.各大购物平台在节假日都是更换App Icon图标 通常有两种方式&#xff1a;1.每换一个新的图标&#xff0c;需要重新上一次AppStore&#xff1b; 2.在项目里预留好未来需要更换的图标&#xff0c;用api触发(或者本地时间判断自动更换) 两种方法各有利弊&#xff0c;第一种 弊&…

「喜迎华诞」手把手教你用微信小程序给头像带上小旗帜

文章目录一、文章前言二、实现原理三、开发步骤四、完整代码五、国庆临近&#xff0c;祝祖国永远繁荣昌盛&#xff01;一、文章前言 2022年是新中国成立73周年&#xff0c;在这个举国欢庆的日子里&#xff0c;让我们给头像上加上小红旗&#xff0c;迎国庆换新颜&#xff0c;一起…

视频倒放怎么制作?快来学会这几个简单的方法

众所周知&#xff0c;如果我们想要让视频更具有观赏性的话&#xff0c;少不了用视频倒放功能来制作视频。不过还是有很多小伙伴不知道视频倒放怎么制作&#xff1f; 下面我就来手把手教你们视频倒放的制作方法&#xff0c;你们快来看看吧&#xff01; 方法一&#xff1a;提词全…

Monaco Editor教程(五): 实现同时多文件编辑,tab切换

背景 上一篇我们讲解了如何设置编辑器的值&#xff0c;获取编辑器的值&#xff0c;以及监听编辑器的内容修改。这些功能对于基础的单文件修改&#xff0c;一次只修改一个文件的业务场景比较友好。但如果是复杂的场景&#xff0c;比如WEB IDE&#xff0c;同时打开一个项目的多个…

聊聊SQL注入

明天是国庆1001,祝大家国庆节快乐!!!这个月还有属于程序员的节日:1024SQL注入问题概述:首先SQL注入是一个非常危险的操作,很可能被一些不怀好意的人钻空导致我们系统出现异常等状况,比如数据库遭到破坏或被入侵。原因:使用JDBC的Statement语句添加SQL语句由于我们的JD…

直播电商开发,源码无加密

随着直播电商的流行&#xff0c;很多企业开始使用商场电商直播系统&#xff0c;该企业使用电商直播系统的优势具体体现在哪里&#xff1f;下面由零七科技小编为您总结企业电商直播系统的优点。 使用电商直播系统的优点&#xff1a; 1、全面展示商品风格和效果。 与在线平台的…

【Django-rest-framework框架】第04回 视图集

目录1. 两个视图基类1.1 GenericAPIview属性和方法1.2 基于APIView写5个接口1.3 基于GenericAPIview写5个接口2. 5个视图扩展类3. 9个视图子类4. 视图集5. 源码分析ViewSetMixin6. 总结7 继承关系画出来,有哪些常用属性或方法写出来 1. 两个视图基类 1.1 GenericAPIview属性和…