在使用 Parameters.jl 时在 Julia 中出现的方法错误

huangapple go评论67阅读模式
英文:

Method error in Julia when using Parameters.jl

问题

我想定义如下变量,但当我添加这一行time::Vector{Float32}=[a:step:b]时不起作用
使用 Parameters

@with_kw mutable struct variables
    InetrpolationDegree::Int = 1
    a::Float32 = 0.0
    b::Float32 = 15.0
    N::Int = 100
    step::Float32 = (b-a)/N
    time::Vector{Float32}=[a:step:b]
end

t = variables(N=100).time;
Δt = variables(N=100).step;
s = variables(N=100).InetrpolationDegree

我收到了以下错误消息

MethodError: 无法将类型为 StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64} 的对象转换为类型 Float32

英文:

I want to define variables as below, but does not when I add the line time::Vector{Float32}=[a:step:b]
using Parameters

@with_kw mutable struct variables
 InetrpolationDegree::Int = 1
        a::Float32 =0.0
        b::Float32 =15.0
        N::Int = 100
     step::Float32 = (b-a)/N
        time::Vector{Float32}=[a:step:b]
end

t=variables(N=100).time;
Δt=variables(N=100).step;
s=variables(N=100).InetrpolationDegree

I got this this error

> MethodError: Cannot convert an object of type StepRangeLen{Float64,
> Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64} to
> an object of type Float32

答案1

得分: 0

你应该知道,通过 a:step:b 构建的对象是 AbstractRange 抽象类型的子类型。因此,将它包装在方括号 [a:step:b] 内不会创建一个 Vector{Float32} 类型的对象!因此,你应该在大括号内声明正确的类型。由于返回的对象是一个 Vector,其中元素是一个 <:AbstractRange 对象(读作:AbstractRange 的子类型),我们可以这样说:

time::Vector{<:AbstractRange}=[a:step:b]
@with_kw mutable struct variables
  InetrpolationDegree::Int = 1
  a::Float32 = 0.0
  b::Float32 = 15.0
  N::Int = 100
  step::Float32 = (b-a)/N
  time::Vector{<:AbstractRange} = [a:step:b]
end;

t = variables(N=100).time;
Δt = variables(N=100).step;
s = variables(N=100).InetrpolationDegree # 返回 1

附加说明

请记住,你还可以使用 Base.@kwdef 而不是 @with_kw

英文:

You should be aware that the constructed object through a:step:b is subtype of the AbstractRange AbstractType. So wrapping it within brackets [a:step:b] won't make an object of type Vector{Float32}! Thus, you should declare the correct type within braces. Since the returned object is a Vector, which in the element is an object <:AbstractRange (read it: subtype of AbstractRange), we can say:
time::Vector{<:AbstractRange}=[a:step:b]

@with_kw mutable struct variables
  InetrpolationDegree::Int = 1
  a::Float32 =0.0
  b::Float32 =15.0
  N::Int = 100
  step::Float32 = (b-a)/N
  time::Vector{<:AbstractRange}=[a:step:b]
end;

t=variables(N=100).time;
Δt=variables(N=100).step;
s=variables(N=100).InetrpolationDegree # returns 1

Additional Note

Keep in mind that you can also use Base.@kwdef rather than @with_kw.

答案2

得分: 0

你的问题似乎是你在括号[]中包裹了你的范围对象,这会将其转换为一组范围的矢量,这可能不是你实际想要的结果。将字段签名更改为:

time::Vector{<:AbstractRange}=[a:step:b]

可以消除错误,但会带来一些不幸的副作用。首先,现在你有一组范围,而不仅仅是一个普通的范围。其次,该字段现在是抽象类型,这对性能不利。

我建议以下两种替代方案:

修复类型签名并移除括号:

@with_kw mutable struct Variables
    InterpolationDegree::Int = 1
    a::Float32 = 0.0f0
    b::Float32 = 15.0f0
    N::Int = 100
    step::Float32 = (b-a)/N
    Time::StepRangeLen{Float32,Float64,Float64,Int64} = (a:step:b)
end

或者,收集向量并修复签名:

@with_kw mutable struct Variables
    InterpolationDegree::Int = 1
    a::Float32 = 0.0f0
    b::Float32 = 15.0f0
    N::Int = 100
    step::Float32 = (b-a)/N
    Time::Vector{Float32} = collect(a:step:b)
end

如果可能的话,我更喜欢第一种替代方案,因为它使用轻量级范围,而不是浪费内存的Vector,特别是对于长时间间隔。

另外两点注意:

  1. 按照惯例,类型名称应该大写:Variables,而不是variables
  2. 你确定你的结构体需要是mutable 吗?不可变的结构体性能更好,可以更安全,避免意外的变更。
英文:

Your problem appears to be that you are wrapping your range-object in brackets, []. That turns it into a Vector of ranges, which may not be what you actually want. Changing the field signature to

time::Vector{<:AbstractRange}=[a:step:b]

removes the error but has some unfortunate side effects. Firstly, you now have a vector of ranges, instead of just a plain range. Secondly, the field is now abstractly typed, which is bad for performance.

I suggest these two alternatives instead:

Fix the type signature and remove the brackets:

@with_kw mutable struct Variables
    InterpolationDegree::Int = 1  # this field was mis-spelled
    a::Float32 = 0.0f0  # using literal float syntax (not strictly necessary)
    b::Float32 = 15.0f0
    N::Int = 100
    step::Float32 = (b-a)/N
    Time::StepRangeLen{Float32,Float64,Float64,Int64} = (a:step:b)
end

Or, collect the vector and fix the signature:

@with_kw mutable struct Variables
    InterpolationDegree::Int = 1
    a::Float32 = 0.0f0
    b::Float32 = 15.0f0
    N::Int = 100
    step::Float32 = (b-a)/N
    Time::Vector{Float32} = collect(a:step:b)
end

I prefer the first alternative, if possible, since it uses a lightweight range, instead of a Vector which wastes memory, especially for long time-intervals.

Two more remarks:

  1. By convention, type names should be capitalized: Variables, not variables.
  2. Are you sure that your struct needs to be mutable? Immutable structs have better performance, and can be safer from accidental mutation.

huangapple
  • 本文由 发表于 2023年2月27日 16:31:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75578252.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定