这是两个真/假
数组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
是否有更好(更快)的解决方案?
答案 0 :(得分:4)
这是jch的答案的轻微变体,但根据&#34,使用位操作而不是理解来选择a
和b
的元素可能会更快;掩模" 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
选择b
或r
的方法是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
如果掩码为true
但a
为false
,or
且true
,则真值表中的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
现在进行一些分析
我的直觉是这个问题的位操作解决方案比使用?
运算符的理解要快得多。对这些操作进行定时表明,对于大型阵列,位操作要快几个数量级,并且内存密集程度要低得多。以下是a
,b
和r
长度为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选择b
和r
中的元素,这相当于您的for
循环,但稍微多一点清晰可辨。