is there any way to check overflow when converting an Array{Int64} to 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
I know one naive way is to check all(typemin(Int32) .< x .< typemax(Int32)). But I am looking for a more efficient method.
Edit:
I tried to compare a devectozied but less elegant function 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
It turns out that g uses less memory and hence much faster than 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)
I found the direct examination method to be faster. Like you discovered above, memory usage is likely the reason. So in this case, you can exchange convenience for run speed and achieve better performance.
You're only concerned with if there will be an error if Array{Int64} when converted to an Array{Int32}. That obviously is the case when that number is > 2^32.
julia> int32(2^42)
0
but trying to represent anything greater than 2^31 - 1 also a problem because of the use of 2's complement.
julia> x = 2^31 - 1
2147483647
julia> int32(x) == x
true
julia> y = 2^31
2147483648
julia> int32(y) == y
false
The 2 functions I used for comparison were
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 will be faster because it will stop immediately as soon as 1 bad value is found, but is faster even under the worst conditions
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)
if the @inbounds macro is used, the speed is consistently increased by approximately 60%
@inbounds v = x[i]
new results
julia> @time for i = 1:1000 check2(z) end
elapsed time: 0.005379673 seconds (0 bytes allocated)
While verifying the correctness, I stumbled on this
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
It looks like check1 is incorrect, 2^31 - 1 can be represented by a 32 bit integer. Instead check1 should use <=.
function check1(x)
all(typemin(Int32) .<= x .<= typemax(Int32))
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With