轨道
/
Julia
Julia
/
练习
/
棘手的概率
棘手的概率

棘手的概率

学习练习

简介

Rational numbers是分数,由一个整数分子除以一个整数分母构成。

例如,我们可以把2//3存成精确的分数,而不是近似的Float64值0.6666...。

这样做的好处是,除了整数溢出这种极端情况,有理数都能保持精确,避免浮点数常常无法避免的舍入误差。

有理数是一种相当简单的数值类型,用法基本符合你的预期。由于从早期版本开始它就是 Julia 的标准类型,大多数函数都会像接受整数和浮点数那样,接受它作为输入。

创建有理数

创建很简单,只要在两个整数之间使用//即可。

julia> 3//4
3//4

julia> a = 3; b = 4;

julia> a//b
3//4

公因数会自动约去,把分数化成“最简形式”:能准确表示该分数的最小整数,并且分母非负。

julia> 5//15
1//3

julia> 5//-15
-1//3

有理数的算术运算

常用的arithmetic operators + - * / ^ %都能用于有理数,效果与其他数值类型基本相同。

表达式中可以包含整数和其他Rational,结果仍是Rational。如果表达式中含有float,结果就是float,精度也会随之(可能)损失。

如果需要float,用float()函数把有理数转换一下即可。通常的做法是:用有理数在漫长的计算过程中保持精度,最后再转换成浮点数。

julia> 3//4 + 1//3  # addition
13//12

julia> 3//4 * 1//3  # multiplication
1//4

julia> 3//4 / 1//3  # division
9//4

julia> 3//4 ^ 2  # exponentiation
3//16

julia> 3//4 + 5  # rational and int => rational
23//4

julia> 3//4 + 5.3  # rational and float => float
6.05

julia> float(3//4)  # casting
0.75

其他运算

在 Julia 中,有理数就是数字。编译器通常会按需转换类型。

不过要注意,比较只在分数具有有限小数表示时才成立:

julia> 3//4 == 0.75
true

julia> 3//4 < 0.74
false

除此之外,比较时应先把Rational转换成Float:

julia> 1//3 == 1/3
false

julia> float(1//3) == 1/3
true

数学函数可以接受有理数作为输入,但可能返回浮点数结果:

julia> sqrt(9//16)
0.75

说明

一家研究机构发现,部分初级研究员在分析中一直使用不太理想的方法。 其中一种做法是:在继续计算之前,先把离散概率直接转成浮点数(也就是实数)。

资深研究员更愿意在计算中使用有理数,这样精度可能更高。他们想知道,初级研究员的这些不良做法是否影响了研究的结果。

研究分为两类:

  • 运行大量测试,每个测试给出一个离散的成功概率,然后计算这些概率的平均值。
  • 测试大量相互独立的事件,把所有事件都发生的总概率相乘计算出来。

资深研究员请你编写一些函数,帮他们判断使用浮点数做的分析中是否存在舍入误差;如果存在误差,还要给出精确的有理数结果。

1. 给出成功次数与试验次数之比

rationalize(successes, trials) 函数接收两个数组:successes 和 trials。 对于下标 i,successes[i] 表示在 trials[i] 次试验中成功的次数。 该函数返回一个数组,其中的元素是成功次数除以试验次数所得的有理数,顺序与输入数组一致。

julia> rationalize([1, 2, 3], [4, 5, 6])
3-element Vector{Rational{Int64}}:
 1//4
 2//5
 1//2

2. 求出与成功次数和试验次数对应的实数概率

同样,probabilities(successes, trials) 函数接收两个数组:successes 和 trials。 它返回一个浮点数数组,其中的元素是成功次数除以试验次数,顺序与输入数组一致。

julia> probabilities([1, 2, 3], [4, 5, 6])
3-element Vector{Float64}:
 0.25
 0.4
 0.5

3. 检查概率的平均值

checkmean(successes, trials) 接收两个数组:successes 和 trials。 它会比较实数概率的平均值与有理数概率的平均值。

  • 如果两个平均值相等,checkmean 返回 true
  • 如果两个平均值不同,checkmean 返回有理数概率。
julia> successes, trials = [9, 4, 7, 8, 6], [22, 22, 11, 17, 12];
julia> checkmean(successes, trials)
true

julia> successes, trials = [6, 5, 9, 8, 9], [21, 19, 13, 25, 22];
julia> checkmean(successes, trials)
1873629//4754750

4. 检查独立概率

checkprob(successes, trials) 接收两个数组:successes 和 trials。 它会比较浮点数概率的总概率与有理数概率的总概率。

  • 如果两个概率相等,checkprob 返回 true
  • 如果两个概率不同,checkprob 返回有理数概率。
julia> successes, trials = [2, 9, 4, 4, 5], [15, 11, 17, 19, 15];
julia> checkprob(successes, trials)
true

julia> successes, trials = [9, 8, 5, 4, 3], [22, 14, 19, 25, 18];
julia> checkprob(sucesses, trials)
12//7315
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Julia Exercism

准备好开始 棘手的概率 了吗?

注册 Exercism,借助 35 个概念128 个练习 和真人导师指导,学习并掌握 Julia,全部免费。