是否存在将数组中的小值归零的通用方法?
小"小"我的意思是绝对值小于某个阈值的元素,如10.0^-5
。
编辑:现在,我循环使用eachindex
。
function sparsify(a, eps)
for i in eachindex(a)
if abs(a[i]) < eps
a[i] = 0
end
end
end
答案 0 :(得分:5)
为什么不直接应用掩码和元素 运算符?
>>> x = rand(Float32, 100)
>>> eps = 0.5
>>> x[abs(x) .< eps] = 0
或作为函数(注意函数修改向量x
inplace):
>>> sparsify!(x, eps) = x[abs(x) .< eps] = 0;
您也可以将0
替换为zero(eltype(x))
,以确保其类型与x
相同。
x .< eps
创建的临时布尔掩码会将x
的每个元素与eps
进行比较。然后,满足该条件的每个元素都将设置为0。
答案 1 :(得分:1)
我最终得到了一个矢量化方法,这个方法要短得多。
sparsify(x, eps) = abs(x) < eps ? 0.0 : x
@vectorize_2arg Float64 sparsify
答案 2 :(得分:1)
选择何种方法取决于您的需求。如果你只需要一个简单的单行,那么矢量化版本就可以了。但是如果你想要最佳性能,循环将更好地为你服务。
以下是一些通过性能进行比较的替代方案。请记住,function zerofy!(x, vmin)
for (val, i) in enumerate(x)
if abs(val) < vmin
x[i] = zero(eltype(x))
end
end
end
zerofy2!(x, vmin) = ( x[abs(x) .< vmin] = zero(eltype(x)) )
zerofy3(x, eps) = abs(x) < eps ? 0.0 : x
@vectorize_2arg Float64 zerofy3!
zerofy4(y, vmin) = map(x -> abs(x)<vmin ? zero(x) : x, y)
zerofy4!(y, vmin) = map!(x -> abs(x)<vmin ? zero(x) : x, y)
function time_zerofy(n, vmin)
x1 = rand(n)
x2, x3, x4, x5 = copy(x1), copy(x1), copy(x1), copy(x1)
@time zerofy!(x1, vmin)
@time zerofy2!(x2, vmin)
@time zerofy3(x3, vmin)
@time zerofy4(x4, vmin)
@time zerofy4!(x5, vmin)
return nothing
end
julia> time_sparse(10^8, 0.1)
0.122510 seconds
1.078589 seconds (73.25 k allocations: 778.590 MB, 5.42% gc time)
0.558914 seconds (2 allocations: 762.940 MB)
0.688640 seconds (5 allocations: 762.940 MB)
0.243921 seconds
版本0.4很慢。这里的时间安排是0.5版本。
zerofy3!
循环(最快)和天真矢量化循环之间存在很大差异。
修改:zerofy3
=&gt; Ax2+VAx*t1=Bx1+VBx*t1
t1=(Bx1-Ax2)/(VAx-VBx)
t2=(Bx2-Ax1)/(VAx-VBx)
因为它不在原地。
答案 3 :(得分:0)
要完成Imanol Luengo的答案,并将其扩展到多个维度,
x[abs.(x) .< eps(eltype(x))] .= zero(eltype(x))