"构造函数:有理数实例"相关问题

我在学习julia中文文档的“构造函数”这一节时,在有理数实例的学习中发现了一个问题。
当我如教程所示构造了我的有理数OurRational后,

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
OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d)
OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...)
OurRational(n::Integer) = OurRational(n,one(n))
⊘(n::Integer, d::Integer) = OurRational(n,d)
⊘(x::OurRational, y::Integer) = x.num ⊘ (x.den*y)
⊘(x::Integer, y::OurRational) = (x*y.den) ⊘ y.num
⊘(x::Complex, y::Real) = complex(real(x) ⊘ y, imag(x) ⊘ y)
⊘(x::Real, y::Complex) = (x*y') ⊘ real(y*y')
function ⊘(x::Complex, y::Complex)
    xy = x*y'
    yy = real(y*y')
    complex(real(xy) ⊘ yy, imag(xy) ⊘ yy)
end

试图去得到一个复数⊘复数的命令的结果时:

z = (1 + 2im) ⊘ (1 - 2im)

会报错:

OurRational{Int64}(1, 2)ERROR: promotion of types OurRational{Int64} and
Int64 failed to change any arguments

我考察了错误原因,可能是由于无法执行complex命令:

complex(real(x) ⊘ y, imag(x) ⊘ y)

因为我测试了执行:

complex(1 ⊘ 2, 3 ⊘ 2)

结果显示相同的错误

OurRational{Int64}(1, 2)ERROR: promotion of types OurRational{Int64} and 
Int64 failed to change any arguments

但如果我运行真正的有理数(“x//y”)的复数化后,则不会报错:

julia> complex(1//2, 3//2)
1//2 + 3//2*im

随后我去看了rational.jl与之相关的内容,似乎和示例中的并无不同:

//(x::Complex, y::Real) = complex(real(x)//y, imag(x)//y)
//(x::Number, y::Complex) = x*conj(y)//abs2(y)

作为一个初学者我不知道为什么我按照教程运行的OurRational会出现这个错误,请求社区的大家指点一下,谢谢大家啦

是不是少定义了一个函数?

Base.complex(x::OurRational, y::OutRational) = 1.0 # change this to the right one!
z = (1 + 2im) ⊘ (1 - 2im) # return 1.0

complex并不知道如何处理两个输入都是自定义的OurRational情况。

1 个赞

感谢您的回复,我添加了新的定义,并得到了结果

function complex(r::OurRational, im::OurRational)
    complex(convert(Float64, r.num) / convert(Float64, r.den),
            convert(Float64, im.num) / convert(Float64, im.den))
end
z = (1 + 2im) ⊘ (1 - 2im)# return -0.6 + 0.8im

感谢您的帮助