通过从另外两个“Bool”数组中随机选择值来创建一个“Bool”数组
Create a `Bool` array by randomly selecting values from two other `Bool` arrays
这里有两个数组true/false
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
是否有更好(更快)的解决方案?
我会这样说:
r = randbit(5)
c = [ r[i] ? a[i] : b[i] for i = 1:5 ]
第一行有效地生成了一个随机布尔值数组 r
(实际上是一个位数组,但这是一个实现细节)。第二行根据 r
中的值从 a
和 b
中选择元素,使用 array comprehension,这相当于你的 for
循环但稍微多一点清晰可辨。
这与 jch 的回答略有不同,但使用位操作可能比理解 select a
和 b
的元素更快=56=] 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
请注意,我已经更正了这个问题的位操作答案
这个问题我原来的回答是说selecta
或者b
根据掩码r
的方法是a&r|b
。然而,由于这个公式缺乏对称性而烦恼,我更仔细地研究了这个问题,生成了一个完整的事实 table 并将公式更正为 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
原来的公式对于真值table中的8个条目之一是错误的,当mask是true
但是a
是false
,or
与 true
b
错误地导致 true
。解决方法是使用 a
和掩码,掩码与 b
的补码,或结果。这是真相table:
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)
因此,如果您使用的是小型数组,这两种技术都可以,但位操作对于非常大的数组更有效。
这里有两个数组true/false
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
是否有更好(更快)的解决方案?
我会这样说:
r = randbit(5)
c = [ r[i] ? a[i] : b[i] for i = 1:5 ]
第一行有效地生成了一个随机布尔值数组 r
(实际上是一个位数组,但这是一个实现细节)。第二行根据 r
中的值从 a
和 b
中选择元素,使用 array comprehension,这相当于你的 for
循环但稍微多一点清晰可辨。
这与 jch 的回答略有不同,但使用位操作可能比理解 select a
和 b
的元素更快=56=] 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
请注意,我已经更正了这个问题的位操作答案
这个问题我原来的回答是说selecta
或者b
根据掩码r
的方法是a&r|b
。然而,由于这个公式缺乏对称性而烦恼,我更仔细地研究了这个问题,生成了一个完整的事实 table 并将公式更正为 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
原来的公式对于真值table中的8个条目之一是错误的,当mask是true
但是a
是false
,or
与 true
b
错误地导致 true
。解决方法是使用 a
和掩码,掩码与 b
的补码,或结果。这是真相table:
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)
因此,如果您使用的是小型数组,这两种技术都可以,但位操作对于非常大的数组更有效。