首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模拟一个概率问题:3个独立的骰子

模拟一个概率问题:3个独立的骰子
EN

Stack Overflow用户
提问于 2022-02-06 13:34:59
回答 1查看 92关注 0票数 3

我决定模拟教科书中的概率问题:

三个公平的骰子是独立滚动的,一个骰子显示6,另两个显示两个不相等数的概率是多少(两者都不等于6)?

假设骰子是公平的,所以“理论”答案将是$\frac{2}{2}{2}{3}=0.5$;我决定在Julia中模拟这一点,下面是我为此编写的函数:

代码语言:javascript
运行
复制
function simulation(n_experiments::Int = 100)
    dice = [DiscreteUniform(1, 6) for i in 1:3] # 3 independent fair dice
    successes = 0
    for trial in 1:n_experiments
        experiment = rand.(dice) # roll
        one_six = sum(r == 6 for r in experiment) == 1 # check if there is only one "6"
        others = filter(num -> num != 6, experiment)
        no_duplicates = length(Set(others)) == 2 # check if other two are distinct
        if no_duplicates
            if one_six
                successes += 1 # count "success"
            end
        end
    end
    return successes / n_experiments
end

我预计这会返回0.5左右的内容,但实际上它在大约10^5次迭代(n_experiments)后返回~0.27。有人能帮我找出密码中的漏洞吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-06 14:08:22

我认为你的代码是对的,但你的数学错了:

代码语言:javascript
运行
复制
julia> function simulation(n_experiments=100)
           chains = rand.(fill(DiscreteUniform(1, 6), 3), n_experiments)
           return (1/n_experiments) * mapreduce(+, chains...) do d1, d2, d3
               (d1 == 6 && d2 != 6 && d3 != 6 && d2 != d3) || (d1 != 6 && d2 == 6 && d3 != 6 && d1 != d3) || (d1 != 6 && d2 != 6 && d3 == 6 && d1 != d2)
           end
       end
simulation (generic function with 1 method)

julia> simulation(10_000)
0.279

julia> count(Iterators.product(1:6, 1:6, 1:6)) do (d1, d2, d3)
           (d1 == 6 && d2 != 6 && d3 != 6 && d2 != d3) || (d1 != 6 && d2 == 6 && d3 != 6 && d1 != d3) || (d1 != 6 && d2 != 6 && d3 == 6 && d1 != d2)
       end 
60

julia> 60 / 6^3
0.2777777777777778

我希望能找到一种简洁的方式来对情况进行编码。因为分配,我避免了你的变体,我的只是详细的确保它是正确的--但是太长了.

附录

下面是具有生成条件的优化变量。与问题无关,而是因为我觉得它很酷。条件公式的功劳属于Bogumił。

代码语言:javascript
运行
复制
julia> @generated function condition(xs::NTuple{N,<:Any}) where {N}
           offdiagonals = ((i, j) for i = 1:N for j = (i+1):N)
           names = Symbol.(:xs, 1:N)
           assignments = [:($(names[i]) = xs[$i]) for i = 1:N]
           comparisons = [:($(names[i]) != $(names[j])) for (i, j) in offdiagonals]
           condition = Expr(:&&, :(maximum(xs) == 6), comparisons...)
           return quote
               $(assignments...)
               $condition
           end
       end
condition (generic function with 1 method)

julia> @code_warntype condition((1,2,3))
MethodInstance for condition(::Tuple{Int64, Int64, Int64})
  from condition(xs::Tuple{Vararg{var"#s17", N}} where var"#s17") where N in Main at REPL[71]:1
Static Parameters
  N = 3
Arguments
  #self#::Core.Const(condition)
  xs::Tuple{Int64, Int64, Int64}
Locals
  xs3::Int64
  xs2::Int64
  xs1::Int64
Body::Bool
1 ─       (xs1 = Base.getindex(xs, 1))
│         (xs2 = Base.getindex(xs, 2))
│         (xs3 = Base.getindex(xs, 3))
│   %4  = Main.maximum(xs)::Int64
│   %5  = (%4 == 6)::Bool
└──       goto #7 if not %5
2 ─ %7  = (xs1 != xs2)::Bool
└──       goto #6 if not %7
3 ─ %9  = (xs1 != xs3)::Bool
└──       goto #5 if not %9
4 ─ %11 = (xs2 != xs3)::Bool
└──       return %11
5 ─       return false
6 ─       return false
7 ─       return false


julia> function simulation(n_experiments=100)
           (1/n_experiments) * sum(1:n_experiments) do _
               dice = (rand(1:6), rand(1:6), rand(1:6))
               condition(dice)
           end
       end
simulation (generic function with 2 methods)

julia> @time simulation(10_000_000)
  0.157303 seconds
0.2777498

这根本没有拨款。sum就像手动循环一样快!

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71007705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档