在朱莉娅(0.6.2),推!偶尔会覆盖推送最后一个元素的所有先前元素。这是一段出现的代码;最后,out
由相同的条目组成。
using Distributions
l = [(0, 10, 1, [1.1; 2.2], [1/3; 2/3], 4)];
out = Array{Float64}[ ]; # output
entry = zeros(Float64,3);
for i = 1:length(l)
row = l[i];
startingtime = row[1];
finishingtime = row[2];
node = row[3];
sizelist = row[4];
sizedistr = row[5];
density = row[6];
t = startingtime;
deltat = rand(Exponential(1/density));
while t + deltat < finishingtime
t = t + deltat;
filetype = rand(Categorical(sizedistr));
size = sizelist[filetype];
entry[1] = t; entry[2] = node; entry[3] = size;
print(entry,"\n");
push!(out, entry);
deltat = rand(Exponential(density));
end;
end;
out
我有点担心重复性,因为在其他类似的情况下,推!工作得很好。那么......这是一个真正的错误吗?或者有一个简单的解决方案吗?提前谢谢!
编辑:好的,澄清:通过再现性,我的意思是在许多其他情况下,推!工作得很好,我没有看到它的特定模式。甚至可能发生在另一台计算机上,此代码运行良好。我不知道。但由于某种原因,对我来说,上面的代码不能正常工作:对于每次运行,它会产生一个由相同条目组成的out
。这是一个输出:
[0.175033, 1.0, 2.2]
[0.24153, 1.0, 2.2]
[4.95478, 1.0, 2.2]
[7.46299, 1.0, 2.2]
Array{Float64,N} where N[[7.46299, 1.0, 2.2], [7.46299, 1.0, 2.2], [7.46299, 1.0, 2.2], [7.46299, 1.0, 2.2]]
打印输出还显示生成时条目实际上是不同的,但它们会在push!
之后重写。这种现象也发生在其他一些不含随机性的代码中,但它太长了(我甚至不知道哪些部分与bug有关,所以我甚至无法减少它)所以我尽量避免在这里包含它。
答案 0 :(得分:1)
这与随机性或push!
无关。您只需将同一个数组(实际上是一个指针)推送到out
,同时每次更改其内容:
julia> entry = zeros(Float64, 3)
3-element Array{Float64,1}:
0.0
0.0
0.0
julia> out = Array{Float64}[]
0-element Array{Array{Float64,N} where N,1}
julia> for t = 1:3
entry[1], entry[2], entry[3] = rand(), rand(), rand()
println(entry)
push!(out, entry)
println(out)
end
[0.913257, 0.413237, 0.612766]
Array{Float64,N} where N[[0.913257, 0.413237, 0.612766]]
[0.00247971, 0.0204771, 0.891242]
Array{Float64,N} where N[[0.00247971, 0.0204771, 0.891242], [0.00247971, 0.0204771, 0.891242]]
[0.847745, 0.742295, 0.0260808]
Array{Float64,N} where N[[0.847745, 0.742295, 0.0260808], [0.847745, 0.742295, 0.0260808], [0.847745, 0.742295, 0.0260808]]
julia> pointer(out[1])
Ptr{Float64} @0x00007f7e0abfaf20
julia> pointer(out[2])
Ptr{Float64} @0x00007f7e0abfaf20
看到了吗?基本上,每次更改相同的entry
,最后在out
中最终都会使用相同的引用三次。
如何避免?只需在循环中指定entry
:
julia> out = Array{Float64}[]
0-element Array{Array{Float64,N} where N,1}
julia> for t = 1:3
entry = rand(3)
println(entry)
push!(out, entry)
println(out)
end
[0.141818, 0.743078, 0.760137]
Array{Float64,N} where N[[0.141818, 0.743078, 0.760137]]
[0.625746, 0.558617, 0.633356]
Array{Float64,N} where N[[0.141818, 0.743078, 0.760137], [0.625746, 0.558617, 0.633356]]
[0.337548, 0.55715, 0.78439]
Array{Float64,N} where N[[0.141818, 0.743078, 0.760137], [0.625746, 0.558617, 0.633356], [0.337548, 0.55715, 0.78439]]
然后你可以完全删除外部声明。你不能避免使用3个单独的entry
,因为你真的需要那么多的分配,如果你想要它们不同......
哦,不需要那些分号。如果那是你的动力,朱莉娅不会自动打印任何东西,比如Matlab。
答案 1 :(得分:1)
在循环的每次迭代中,您将相同的 entry
向量附加到out
。在每次迭代中,您只是变异entry
,有效地为最终out
数组中的所有实例进行变异。
使用更简单的代码块更容易看到:
julia> entry = zeros(3);
julia> out = [];
julia> for i in 1:3
entry[1] = rand()
@show entry
push!(out, entry)
end
entry = [0.580382, 0.0, 0.0]
entry = [0.210324, 0.0, 0.0]
entry = [0.658214, 0.0, 0.0]
julia> out
3-element Array{Any,1}:
[0.658214, 0.0, 0.0]
[0.658214, 0.0, 0.0]
[0.658214, 0.0, 0.0]
最终的out
包含看似重复的元素,因为它中的每个元素都是你在循环中修改的相同的向量:
julia> out[1] === out[2] === out[3]
true
如果您希望out
中的每个条目都是一个单独的向量,那么您需要在每次迭代时构造一个新的entry
或在copy()
之前将其推入{{1} }}。例如:
out
如果您不想julia> out = [];
julia> for i in 1:3
entry[1] = rand()
@show entry
push!(out, copy(entry))
end
entry = [0.992697, 0.0, 0.0]
entry = [0.0971598, 0.0, 0.0]
entry = [0.918921, 0.0, 0.0]
julia> out
3-element Array{Any,1}:
[0.992697, 0.0, 0.0]
[0.0971598, 0.0, 0.0]
[0.918921, 0.0, 0.0]
而不是:
copy()
只是做:
entry[1] = t; entry[2] = node; entry[3] = size;
print(entry,"\n");
push!(out, entry);