How to define an array of any float type in Julia?

久未见 提交于 2021-01-28 01:29:01

问题


I tried Array{AbstractFloat,1}, but this does not work as Array{Float64,1} <: Array{AbstractFloat,1} is false, even though Float64 <: AbstractFloat is true.


回答1:


If you want an vector which can contain any kind of floating-point value, then the correct type is Vector{AbstractFloat}, which can be constructed like this:

julia> v = AbstractFloat[]
AbstractFloat[]

julia> push!(v, 1.5)
1-element Vector{AbstractFloat}:
 1.5

julia> push!(v, big(2.0)^1000)
2-element Vector{AbstractFloat}:
 1.5
 1.071508607186267320948425049060001810561404811705533607443750388370351051124936e+301

julia> map(typeof, v)
2-element Vector{DataType}:
 Float64
 BigFloat

julia> push!(v, "oy, I'm not a float!")
ERROR: MethodError: Cannot `convert` an object of type String to an object

You are correct that Vector{Float64} is not a subtype of Vector{AbstractFloat}. This is because subtyping of parametric types in Julia is invariant (not covariant or even contravariant). Even more generally, no concrete type is a subtype of any other concrete type and Vector{Float64} and Vector{AbstractFloat} are both concrete types since they are the types of actual objects:

julia> typeof(v)
Vector{AbstractFloat} = Array{AbstractFloat,1}

julia> typeof([1.5])
Vector{Float64} = Array{Float64,1}

If you want an abstract type which includes both of these concrete types as well as any other vector of floating-point values, that can be expressed as Vector{<:AbstractFloat}:

julia> Vector{AbstractFloat} <: Vector{<:AbstractFloat}
true

julia> Vector{Float64} <: Vector{<:AbstractFloat}
true

julia> Vector{Union{Float64, BigFloat}} <: Vector{<:AbstractFloat}
true

julia> Vector{String} <: Vector{<:AbstractFloat}
false

However, this type is abstract and you cannot create an instance of it. You can, however, use it for dispatch and write a method that will apply to any vector of floating-point values:

f(v::Vector{<:AbstractFloat}) = "a vector of floats"
f(v::Vector) = "a vector but not of floats"
f(x::Any) = "not a vector at all"

Here's this function in action:

julia> f(v)
"a vector of floats"

julia> f([1.5])
"a vector of floats"

julia> f(Union{Float64,BigFloat}[1.5, big(2.0)])
"a vector of floats"

julia> f([1, 2, 3])
"a vector but not of floats"

julia> f("nope")
"not a vector at all"

In short, the element type of a vector has to be an actual type, such as Float64 or AbstractFloat. You can expess the set of types of all floating-point vectors as Vector{<:AbstractFloat} but this cannot be the type of any vector because <:AbstractFloat is not a type, it's an upper bound on types. You can, however, use Vector{<:AbstractFloat} to define methods which operate on any vector of floats, regardless of specific element type (as long as the element type is some kind of float).



来源:https://stackoverflow.com/questions/62972685/how-to-define-an-array-of-any-float-type-in-julia

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!