以下代码来自 Julia 手册。我的问题如下。
julia> struct OurRational{T<:Integer} <: Real
num::T
den::T
function OurRational{T}(num::T, den::T) where T<:Integer
if num == 0 && den == 0
error("invalid rational: 0//0")
end
num = flipsign(num, den)
den = flipsign(den, den)
g = gcd(num, den)
num = div(num, g)
den = div(den, g)
new(num, den)
end
end
julia> OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d)
OurRational
julia> OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...)
OurRational
julia> OurRational(n::Integer) = OurRational(n,one(n))
OurRational
julia> ⊘(n::Integer, d::Integer) = OurRational(n,d)
⊘ (generic function with 1 method)
julia> ⊘(x::OurRational, y::Integer) = x.num ⊘ (x.den*y)
⊘ (generic function with 2 methods)
julia> ⊘(x::Integer, y::OurRational) = (x*y.den) ⊘ y.num
⊘ (generic function with 3 methods)
julia> ⊘(x::Complex, y::Real) = complex(real(x) ⊘ y, imag(x) ⊘ y)
⊘ (generic function with 4 methods)
julia> ⊘(x::Real, y::Complex) = (x*y') ⊘ real(y*y')
⊘ (generic function with 5 methods)
julia> function ⊘(x::Complex, y::Complex)
xy = x*y'
yy = real(y*y')
complex(real(xy) ⊘ yy, imag(xy) ⊘ yy)
end
⊘ (generic function with 6 methods)
作为这些定义的结果,手册给出了这个例子
julia> z = (1+2im)⊘(1-2im);
Julia> typeof(z)
Complex{OurRational{Int64}}
这很好用......除非你省略“;”
julia> z = (1+2im)⊘(1-2im)
OurRational{Int64}(-3, 5)Error showing value of type Complex{OurRational{Int64}}:
ERROR: promotion of types OurRational{Int64} and Int64 failed to change any arguments
Stacktrace:
[1] error(::String, ::String, ::String)
@ Base ./error.jl:44
[2] sametype_error(input::Tuple{OurRational{Int64}, Int64})
@ Base ./promotion.jl:417
[3] not_sametype(x::Tuple{OurRational{Int64}, Int64}, y::Tuple{OurRational{Int64}, Int64})
@ Base ./promotion.jl:411
[4] promote
@ ./promotion.jl:394 [inlined]
[5] <(x::OurRational{Int64}, y::Int64)
@ Base ./promotion.jl:462
[6] signbit(x::OurRational{Int64})
我不知道为什么。如果您使用内置的 Rational 运算符
julia> z = (1+2im)//(1-2im)
没问题。
有什么想法吗?
根本问题是
OurRational{Int}
和 Int
是不兼容的类型:Int
无法转换为 OurRational{Int}
。检查堆栈跟踪将显示以下内容:
OurRational{Int64}(-3, 5)ERROR: promotion of types OurRational{Int64} and Int64 failed to change any arguments
Stacktrace:
[1] error(::String, ::String, ::String)
@ Base ./error.jl:44
[2] sametype_error(input::Tuple{OurRational{Int64}, Int64})
@ Base ./promotion.jl:417
[3] not_sametype(x::Tuple{OurRational{Int64}, Int64}, y::Tuple{OurRational{Int64}, Int64})
@ Base ./promotion.jl:411
[4] promote <-- issue here ********
@ ./promotion.jl:394 [inlined]
[5] <(x::OurRational{Int64}, y::Int64)
@ Base ./promotion.jl:462
[6] signbit(x::OurRational{Int64})
@ Base ./number.jl:137
[7] show(io::IOContext{Base.TTY}, z::Complex{OurRational{Int64}})
@ Base ./complex.jl:201
[8] show(io::IOContext{Base.TTY}, ::MIME{Symbol("text/plain")}, x::Complex{OurRational{Int64}})
@ Base.Multimedia ./multimedia.jl:47
<snip>
要解决此问题,请定义:
Base.promote_rule(::Type{OurRational{T}}, ::Type{S}) where {T,S} =
OurRational{promote_type(T, S)}
现在……
OurRational{Int64}(-3, 5)ERROR: MethodError: no method matching OurRational{Int64}(::Int64)
Closest candidates are:
OurRational{T}(::T, ::T) where T<:Integer
@ Main ~/Offline-Documents/Scratchpad/f.jl:5
(::Type{T})(::T) where T<:Number
@ Core boot.jl:792
(::Type{T})(::Complex) where T<:Real
@ Base complex.jl:44
...
Stacktrace:
<snip>
好吧,让我们定义一下:
OurRational{T}(n::T) where {T<:Integer} = OurRational(n)
不完全在那里......
OurRational{Int64}(-3, 5)ERROR: < not defined for OurRational{Int64}
Stacktrace:
<snip>
再试一次:
# actual implementation left as exercise
Base.:(<)(x::OurRational{S}, y::OurRational{T}) where {S,T} = x.num//x.den < y.num//y.den
成功!
julia> z = (1 + 2im) ⊘ (1 - 2im)
OurRational{Int64}(-3, 5) + OurRational{Int64}(4, 5)*im