Julia 类型提升

Julia 类型提升

在涉及多个类型互操作的过程中,比如累加或者其他算术运算,一般需要将这些值先转换为相同的类型,以保证它们具有一致的内存结构,同时目标类型也会选择“较大”的类。所谓“较大”,指的是该类型能够准确地容纳所有的操作数及计算结果,通常是这些操作数类型中表达能力最强的一个。例如浮点值3.56和整型值8在一起运算时,数值8会被提升为浮点型,因为整型没有小数部分,所以没有浮点型的表达力强。

这样的过程在Julia中称为“类型提升”Promotion)。对于任意类型、数量的操作数,可以通过promote()函数将它们转为共同的类型。例如:

julia> promote(UInt8(1), Int32(1), UInt32(1))         # Tuple{UInt32, UInt32, UInt32}
(0x00000001, 0x00000001, 0x00000001)

julia> promote(Int32(1), Float32(1.0), Float16(1.0))  # Tuple{Float32, Float32, Float32}
(1.0f0, 1.0f0, 1.0f0)

julia> promote(pi, 1//2)                              # Tuple{Float64, Float64}
(3.141592653589793, 0.5)

julia> promote(Int64(1), 1//2)                        # Tuple{Rational{Int64}, Rational{Int64}}
(1//1, 1//2)
julia> promote(1//2, Float32(1))                      # Tuple{Float32, Float32}
(0.5f0, 1.0f0)

julia> promote(1+2im, Float64(1))                     # Tuple{Complex{Float64}, Complex{Float64}}
(1.0 + 2.0im, 1.0 + 0.0im)

在这样的类型提升系统中:

  • 浮点数会被提升到更大的浮点类型;
  • 整型会被提升到更大的整型;
  • 整型与浮点型混合时,会被提升到足够大的浮点型以能容纳所有的值;
  • 整型与有理数混合时,会被提升到有理数类型;
  • 有理数与浮点数混合时,会被提升到浮点数;
  • 复数与实数混合时,会被提升到相近的复数类型。

可见提升过程并非像看起来那样是隐式、自动进行的,这是因为在Julia内部已经定义了大量的类型提升规则。在多类型混合计算时,Julia只是遵循了这些规则实施而已。事实上,Julia中有一种多态分发机制,能够根据参数列表的差异选择同名函数的不同实现方法。所以Julia对类型有着较为严格的控制,不会随意对类型进行自动转换,尤其是函数的输入参数。运算符是语法有些特别的函数对象,操作数便是其输入参数。所以运算符也遵循多态机制,不会自动进行参数类型的转换,所谓的自动提升只是因为有对应规则的存在。

如果因故需要自定义类型提升规则(比如声明了新的类型),则可以通过promote_rule()函数实现,例如:

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

表示当Float64与Float32混合计算时,目标类型采用Float64类型。如果运算中遇到了两者作为操作数的情况,Julia内部便会通过promote()函数依照上述规则,将操作数均转换为Float64类型,然后再进行计算得到最终的结果。在我们声明创建了自己的新类型时,可以通过上述这样的机制,将其对接到Julia的类型提升系统中。

因为Julia对类型的严格控制,所以若要针对各种具体类型重复地定义某个函数的实现方法,以多态的方式支持各种参数组合是极为麻烦的。不过,我们可以借助抽象类型的特点,并结合类型提升机制,简洁高效地实现这样的需求。例如:

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

其中,四则运算为了能够适应任意两个数值类型,在参数类型中限定为抽象类型,这样可以接收整型、浮点型、复数等类型作为参数,并在函数实现体中通过类型提升机制将它们进行统一处理。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!