简体   繁体   中英

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

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 .

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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