Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ways to check overflow when converting Array{Int64} to Array{Int32}

Tags:

julia

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)
like image 528
Randy Lai Avatar asked Jul 09 '26 23:07

Randy Lai


1 Answers

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.

assumption

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

comparison

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

results

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)

embellished

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)

verification

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
like image 196
waTeim Avatar answered Jul 13 '26 18:07

waTeim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!