99re热视频这里只精品,久久久天堂国产精品女人,国产av一区二区三区,久久久精品成人免费看片,99久久精品免费看国产一区二区三区

Julia 類(lèi)型轉(zhuǎn)換和類(lèi)型提升

2018-08-12 21:25 更新

類(lèi)型轉(zhuǎn)換和類(lèi)型提升

Julia 可以將數(shù)學(xué)運(yùn)算符的參數(shù)提升為同一個(gè)類(lèi)型,這些參數(shù)的類(lèi)型曾經(jīng)在整數(shù)和浮點(diǎn)數(shù) ,數(shù)學(xué)運(yùn)算和基本函數(shù)類(lèi)型,及方法中提到過(guò)。

在某種意義上,Julia 是“非自動(dòng)類(lèi)型提升”的:數(shù)學(xué)運(yùn)算符只是有特殊語(yǔ)法的函數(shù),函數(shù)的參數(shù)不會(huì)被自動(dòng)轉(zhuǎn)換。但通過(guò)重載,仍能做到“自動(dòng)”類(lèi)型提升。

類(lèi)型轉(zhuǎn)換

convert 函數(shù)用于將值轉(zhuǎn)換為各種類(lèi)型。它有兩個(gè)參數(shù):第一個(gè)是類(lèi)型對(duì)象,第二個(gè)是要轉(zhuǎn)換的值;返回值是轉(zhuǎn)換為指定類(lèi)型的值:

    julia> x = 12
    12

    julia> typeof(x)
    Int64

    julia> convert(Uint8, x)
    0x0c

    julia> typeof(ans)
    Uint8

    julia> convert(FloatingPoint, x)
    12.0

    julia> typeof(ans)
    Float64

遇到不能轉(zhuǎn)換時(shí),convert 會(huì)引發(fā) “no method” 錯(cuò)誤:

    julia> convert(FloatingPoint, "foo")
    ERROR: `convert` has no method matching convert(::Type{FloatingPoint}, ::ASCIIString)
     in convert at base.jl:13

Julia 不做字符串和數(shù)字之間的類(lèi)型轉(zhuǎn)換。

定義新類(lèi)型轉(zhuǎn)換

要定義新類(lèi)型轉(zhuǎn)換,只需給 convert 提供新方法即可。下例將數(shù)值轉(zhuǎn)換為布爾值:

convert(::Type{Bool}, x::Number) = (x!=0)

此方法第一個(gè)參數(shù)的類(lèi)型是單態(tài)類(lèi)型, BoolType{Bool} 的唯一實(shí)例。此方法僅在第一個(gè)參數(shù)是 Bool 才調(diào)用。注意第一個(gè)參數(shù)使用的語(yǔ)法:參數(shù)的名稱(chēng)在 :: 之前是省略的,只給出了參數(shù)的類(lèi)型。這是 Julia 中對(duì)于一個(gè)函數(shù)參數(shù),如果其類(lèi)型是指定但該參數(shù)的值在函數(shù)體中從未使用過(guò),那么語(yǔ)法會(huì)被使用,在這個(gè)例子中,因?yàn)閰?shù)是單態(tài)類(lèi)型,就永遠(yuǎn)不會(huì)有任何理由會(huì)在函數(shù)體中使用它的值。

轉(zhuǎn)換時(shí)檢查數(shù)值是否為 0 :

    julia> convert(Bool, 1)
    true

    julia> convert(Bool, 0)
    false

    julia> convert(Bool, 1im)
    ERROR: InexactError()
     in convert at complex.jl:18

    julia> convert(Bool, 0im)
    false

實(shí)際使用的類(lèi)型轉(zhuǎn)換都比較復(fù)雜,下例是 Julia 中的一個(gè)實(shí)現(xiàn):

    convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) :
                                               throw(InexactError()))

    julia> convert(Bool, 1im)
    InexactError()
     in convert at complex.jl:40

案例:分?jǐn)?shù)類(lèi)型轉(zhuǎn)換

繼續(xù) Julia 的 Rational 類(lèi)型的案例研究, rational.jl 中類(lèi)型轉(zhuǎn)換的聲明緊跟在類(lèi)型聲明和構(gòu)造函數(shù)之后:

    convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational(convert(T,x.num),convert(T,x.den))
    convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational(convert(T,x), convert(T,1))

    function convert{T<:Integer}(::Type{Rational{T}}, x::FloatingPoint, tol::Real)
        if isnan(x); return zero(T)//zero(T); end
        if isinf(x); return sign(x)//zero(T); end
        y = x
        a = d = one(T)
        b = c = zero(T)
        while true
            f = convert(T,round(y)); y -= f
            a, b, c, d = f*a+c, f*b+d, a, b
            if y == 0 || abs(a/b-x) <= tol
                return a//b
            end
            y = 1/y
        end
    end
    convert{T<:Integer}(rt::Type{Rational{T}}, x::FloatingPoint) = convert(rt,x,eps(x))

    convert{T<:FloatingPoint}(::Type{T}, x::Rational) = convert(T,x.num)/convert(T,x.den)
    convert{T<:Integer}(::Type{T}, x::Rational) = div(convert(T,x.num),convert(T,x.den))

前四個(gè)定義可確保 a//b == convert(Rational{Int64}, a/b)。后兩個(gè)把分?jǐn)?shù)轉(zhuǎn)換為浮點(diǎn)數(shù)和整數(shù)類(lèi)型。

類(lèi)型提升

類(lèi)型提升是指將各種類(lèi)型的值轉(zhuǎn)換為同一類(lèi)型。它與類(lèi)型等級(jí)關(guān)系無(wú)關(guān),例如,每個(gè) Int32 值都可以被表示為 Float64 值,但 Int32 不是 Float64 的子類(lèi)型。

Julia 使用 promote 函數(shù)來(lái)做類(lèi)型提升,其參數(shù)個(gè)數(shù)可以是任意多,它返回同樣個(gè)數(shù)的同一類(lèi)型的多元組;如果不能提升,則拋出異常。類(lèi)型提升常用來(lái)將數(shù)值參數(shù)轉(zhuǎn)換為同一類(lèi)型:

    julia> promote(1, 2.5)
    (1.0,2.5)

    julia> promote(1, 2.5, 3)
    (1.0,2.5,3.0)

    julia> promote(2, 3//4)
    (2//1,3//4)

    julia> promote(1, 2.5, 3, 3//4)
    (1.0,2.5,3.0,0.75)

    julia> promote(1.5, im)
    (1.5 + 0.0im,0.0 + 1.0im)

    julia> promote(1 + 2im, 3//4)
    (1//1 + 2//1*im,3//4 + 0//1*im)

浮點(diǎn)數(shù)值提升為最高的浮點(diǎn)數(shù)類(lèi)型。整數(shù)值提升為本地機(jī)器的原生字長(zhǎng)或最高的整數(shù)值類(lèi)型。既有整數(shù)也有浮點(diǎn)數(shù)時(shí),提升為可以包括所有值的浮點(diǎn)數(shù)類(lèi)型。既有整數(shù)也有分?jǐn)?shù)時(shí),提升為分?jǐn)?shù)。既有分?jǐn)?shù)也有浮點(diǎn)數(shù)時(shí),提升為浮點(diǎn)數(shù)。既有復(fù)數(shù)也有實(shí)數(shù)時(shí),提升為適當(dāng)?shù)膹?fù)數(shù)。

數(shù)值運(yùn)算中,數(shù)學(xué)運(yùn)算符 +, -, */ 等方法定義,都“巧妙”的應(yīng)用了類(lèi)型提升。下例是 promotion.jl 中的一些定義:

    +(x::Number, y::Number) = +(promote(x,y)...)
    -(x::Number, y::Number) = -(promote(x,y)...)
    *(x::Number, y::Number) = *(promote(x,y)...)
    /(x::Number, y::Number) = /(promote(x,y)...)

promotion.jl 中還定義了其它算術(shù)和數(shù)學(xué)運(yùn)算類(lèi)型提升的方法,但 Julia 標(biāo)準(zhǔn)庫(kù)中幾乎沒(méi)有調(diào)用 promote 。 promote 一般用在外部構(gòu)造方法中,便于使構(gòu)造函數(shù)適應(yīng)各種不同類(lèi)型的參數(shù)。rational.jl 中提供了如下的外部構(gòu)造方法:

    Rational(n::Integer, d::Integer) = Rational(promote(n,d)...)

此方法的例子:

    julia> Rational(int8(15),int32(-5))
    -3//1

    julia> typeof(ans)
    Rational{Int64} (constructor with 1 method)

對(duì)自定義類(lèi)型來(lái)說(shuō),最好由程序員給構(gòu)造函數(shù)顯式提供所期待的類(lèi)型。但處理數(shù)值問(wèn)題時(shí),做自動(dòng)類(lèi)型提升比較方便。

定義類(lèi)型提升規(guī)則

盡管可以直接給 promote 函數(shù)定義方法,但這太麻煩了。我們用輔助函數(shù) promote_rule 來(lái)定義 promote 的行為。 promote_rule 函數(shù)接收類(lèi)型對(duì)象對(duì)兒,返回另一個(gè)類(lèi)型對(duì)象。此函數(shù)將參數(shù)中的類(lèi)型的實(shí)例,提升為要返回的類(lèi)型:

    promote_rule(::Type{Float64}, ::Type{Float32} ) = Float64

提升后的類(lèi)型不需要與函數(shù)的參數(shù)類(lèi)型相同。下面是 Julia 標(biāo)準(zhǔn)庫(kù)中的例子:

    promote_rule(::Type{Uint8}, ::Type{Int8}) = Int
    promote_rule(::Type{Char}, ::Type{Uint8}) = Int32

不需要同時(shí)定義 promote_rule(::Type{A}, ::Type{B})promote_rule(::Type{B}, ::Type{A}) —— promote_rule 函數(shù)在提升過(guò)程中隱含了對(duì)稱(chēng)性。

promote_type 函數(shù)使用 promote_rule 函數(shù)來(lái)定義,它接收任意個(gè)數(shù)的類(lèi)型對(duì)象,返回它們作為 promote 參數(shù)時(shí),所應(yīng)返回值的公共類(lèi)型。因此可以使用 promote_type 來(lái)了解特定類(lèi)型的組合會(huì)提升為哪種類(lèi)型:

    julia> promote_type(Int8, Uint16)
    Int64

promote 使用 promote_type 來(lái)決定類(lèi)型提升時(shí)要把參數(shù)值轉(zhuǎn)換為哪種類(lèi)型。完整的類(lèi)型提升機(jī)制可見(jiàn) promotion.jl,一共有 35 行。

案例:分?jǐn)?shù)類(lèi)型提升

我們結(jié)束 Julia 分?jǐn)?shù)類(lèi)型的案例:

    promote_rule{T<:Integer}(::Type{Rational{T}}, ::Type{T}) = Rational{T}
    promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)}
    promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)}
    promote_rule{T<:Integer,S<:FloatingPoint}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S)
以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)