繁体   English   中英

将Array {Int64}转换为Array {Int32}时检查溢出的方法

[英]ways to check overflow when converting Array{Int64} to Array{Int32}

有什么方法可以在将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)

我发现直接检查方法更快。 就像你上面发现的那样,内存使用可能就是原因。 因此,在这种情况下,您可以为运行速度交换便利性并获得更好的性能。

假设

您只关心转换为数组{Int32}Array {Int64}是否会出错。 当数字大于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应该使用<=

function check1(x) 
   all(typemin(Int32) .<= x .<= typemax(Int32))
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM