通过从另外两个`Bool`数组中随机选择值来创建一个`Bool`数组

时间:2015-02-05 23:02:42

标签: arrays boolean julia

这是两个真/假

数组
a = [true, true, false, true, false]
b = [true, false, false, false, true]

我愿意制作一个新数组c,其中c的每个元素来自a或来自b的概率相等

以下是我找到的两个解决方案:

c=trues(5)
for i = 1:5
  c[i] = rand() > 0.5 ? a[i] : b[i]
end

c=trues(5)
ab = hcat(a,b)
which = sample([1,2], 5)
for i = 1:5
  c[i] = ab[i,which[i]]
end

是否有更好(更快)的解决方案?

2 个答案:

答案 0 :(得分:4)

这是jch的答案的轻微变体,但根据&#34,使用位操作而不是理解来选择ab的元素可能会更快;掩模" r

julia> r = bitrand(5)
5-element BitArray{1}:
  true
  true
 false
 false
 false

julia> r&a | ~r&b
5-element BitArray{1}:
  true
  true
  false
  false
  true

请注意,我已经纠正了对此问题的位操作答案

在我对此问题的原始回答中,我说根据掩码a选择br的方法是a&r|b。然而,由于这个公式缺乏对称性而烦恼,我更仔细地研究了这个问题,生成了一个完整的真值表并将公式更正为r&a | ~r&b

julia> r = [trues(4), falses(4)]
julia> a = [trues(2), falses(2)]
julia> a = [a, a]
julia> b = [true, false]
julia> b = [b, b, b, b]
julia> c = r&a | ~r&b
julia> nocigar = a&r|b
julia> q = [r[i] ? a[i] : b[i] for i in 1:length(a)]

julia> all([c[i] == q[i] for i in 1:length(a)])
true

julia> all([nocigar[i] == q[i] for i in 1:length(a)])
false

如果掩码为trueafalseortrue,则真值表中的8个条目之一的原始公式出错1}} b错误地导致true。修复的是和a的掩码,掩码与b的补码,或者结果。这是真相表:

julia> hcat(a, b, r, c, nocigar)
8x5 Array{Bool,2}:
  true   true   true   true   true
  true  false   true   true   true
 false   true   true  false   true
 false  false   true  false  false
  true   true  false   true   true
  true  false  false  false  false
 false   true  false   true   true
 false  false  false  false  false

现在进行一些分析

我的直觉是这个问题的位操作解决方案比使用?运算符的理解要快得多。对这些操作进行定时表明,对于大型阵列,位操作要快几个数量级,并且内存密集程度要低得多。以下是abr长度为10 ^ 6时的结果:

julia> a = bitrand(10^6)
...

julia> @time c = r&a | ~r&b
elapsed time: 0.000607186 seconds (500496 bytes allocated)

julia> @time c = [r[i] ? a[i] : b[i] for i in 1:length(a)]
elapsed time: 0.446756657 seconds (167967416 bytes allocated, 16.91% gc time)

多次运行这些分配可产生一致的结果。对于较短的数组,长度为100,执行时间差别不大,尽管理解使用了更多的内存:

julia> a = bitrand(100)
...

julia> @time c = r&a | ~r&b
elapsed time: 1.3979e-5 seconds (464 bytes allocated)

julia> @time c = [r[i] ? a[i] : b[i] for i in 1:length(a)]
elapsed time: 5.326e-5 seconds (10520 bytes allocated)

因此,如果您正在使用小型数组,那么这两种技术都可以,但对于非常大的数组,位操作更有效。

答案 1 :(得分:2)

我想说的是:

r = randbit(5)
c = [ r[i] ? a[i] : b[i] for i = 1:5 ]

第一行有效地生成随机布尔值的数组r(实际上是一个比特阵列,但这是一个实现细节)。第二行根据a中的值,使用array comprehension选择br中的元素,这相当于您的for循环,但稍微多一点清晰可辨。