有什么方法可以在将Array {Int64}转换为Array {Int32}时检查溢出吗?
julia> x = [0,100,2^50]
3-element Array{Int64,1}:
0
100
1125899906842624
julia> int32(x)
3-element Array{Int32,1}:
0
100
0
我知道一种天真的方法是检查all(typemin(Int32) .< x .< typemax(Int32))
。但我正在寻找一种更有效的方法。
编辑:
我试图比较一个devectozied但不太优雅的函数g
。
f(x::Array{Int64, 1}) = all(typemin(Int32) .< x .< typemax(Int32))
function g(x::Array{Int64, 1})
a = typemin(Int32)
b = typemax(Int32)
for z in x
if !(a<z<b)
return false
end
end
return true
end
x = convert(Array, (2^31-10000):(2^31));
@time for i in 1:1000; f(x); end
@time for i in 1:1000; g(x); end
事实证明g
使用的内存更少,因此比f
快得多:
julia> @time for i in 1:1000; f(x); end
elapsed time: 0.046384046 seconds (13186456 bytes allocated)
julia> @time for i in 1:1000; g(x); end
elapsed time: 0.015128743 seconds (7824 bytes allocated)
答案 0 :(得分:2)
我发现直接检查方法更快。就像你上面发现的那样,内存使用可能就是原因。因此,在这种情况下,您可以为运行速度交换便利性并获得更好的性能。
您只关心转换为数组{Int32} 时数组{Int64} 是否会出错。当这个数字是&gt;时显然就是这种情况。 2 ^ 32
julia> int32(2^42)
0
但是由于使用了2的补码,试图表示大于2 ^ 31 - 1的任何东西也是个问题。
julia> x = 2^31 - 1
2147483647
julia> int32(x) == x
true
julia> y = 2^31
2147483648
julia> int32(y) == y
false
我用于比较的两个函数是
function check1(x)
all(typemin(Int32) .< x .< typemax(Int32))
end
function check2(x)
ok = true;
const min = -2^31
const max = 2^31 - 1;
for i = 1:length(x)
v = x[i]
if v > max || v < min
ok = false;
break;
end
end
ok
end
check2会更快,因为一旦找到1个坏值就会立即停止,但即使在最恶劣的条件下也会更快
julia> z = convert(Array{Int64},ones(10000));
julia> @time for i = 1:1000 check2(z) end
elapsed time: 0.008574832 seconds (0 bytes allocated)
julia> @time for i = 1:1000 check1(z) end
elapsed time: 0.036393418 seconds (13184000 bytes allocated)
如果使用 @inbounds 宏,速度将持续增加约60%
@inbounds v = x[i]
新结果
julia> @time for i = 1:1000 check2(z) end
elapsed time: 0.005379673 seconds (0 bytes allocated)
在验证正确性的同时,我偶然发现了这个
julia> u = [ 2^31 - 2; 2^31 - 1; 2^31 ]
3-element Array{Int64,1}:
2147483646
2147483647
2147483648
julia> for n in u println(check1([n])) end
true
false
false
julia> for n in u println(check2([n])) end
true
true
false
看起来check1不正确,2 ^ 31-1可以用32位整数表示。相反,check1应使用&lt; = 。
function check1(x)
all(typemin(Int32) .<= x .<= typemax(Int32))
end