Julia语言程序设计
上QQ阅读APP看书,第一时间看更新

3.4 有理数型

有理数与无理数相对,也是实数集合的子集,可以简单地认为是分子与分母均为整数的分数。

在Julia中直接提供了这种数值的表达方式,其原型(其中涉及的抽象类型、类型参数化等概念会在后续章节中详述)为:


Rational{T <: Integer} <: Real

其中,Rational是有理数的类型名;Integer是Julia中定义的抽象类型(后文介绍),用于限定分子与分母都必须是上文中Int8、Int16等具体整数类型的一种;Real是抽象类型,表达的是Rational同浮点型、无理数型一样,都是实数的一种。

Rational类型是Julia中特有的,以“分子//分母”格式表达。其中双斜线并非是运算符,而是表达有理数结构的特定操作符。例如:


julia> 2//3                 # 分子与分母都是Int64类型
2//3

julia> typeof(ans)
Rational{Int64}

julia> Int8(2)//Int32(7)    # 分子是Int8类型,而分母是Int32类型
2//7

julia> typeof(ans)
Rational{Int32}             # 类型被统一为Int32

可见,分子与分母为不同整型时,Julia会通过必要的隐式转换,将两者的类型进行统一。而且创建的Rational数值在Julia内部会被约分为标准形式,确保分母不为负数,例如:


julia> UInt32(2)//Int8(10)
1//5

julia> 5//25                                # 被约分
1//5

julia> 1//-2                                # 负号被放于分子上
-1//2

julia> -2//4
-1//2

如此一来,数学意义上相等的有理数,在语言内部的表达便是唯一的。

由于对无穷值的支持,所以在Rational对象中允许分母为0,但不允许分子和分母同时为0,例如:


julia> 5//0 
1//0 

julia> -3//0 
-1//0 

julia> typeof(ans) 
Rational{Int64}

julia> 0//0 
ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) 

其中,前两个除零有理数定义成功,且都被约分为同一形式;但后一个因为分子和分母都为0,所以创建失败。

显然,如果分子或分母中任意一个为浮点值,创建Rational数值对象也会失败,例如:


julia> 1.2//3
ERROR: MethodError: no method matching //(::Float64, ::Int64)

julia> 2//3.1
ERROR: MethodError: no method matching //(::Int64, ::Float64)

因为Rational的声明中限定了分子、分母的类型必须是整型的一种。

当然,Rational类型的有理数值均可转换到浮点值,例如:


julia> Float64(3//2)
1.5

julia> Float64(-4//-12)
0.3333333333333333

julia> Float64(5//0)
Inf                    # 分母为0的正有理数,对应正无穷

julia> Float64(-3//0)
-Inf                   # 分母为0的负有理数,对应负无穷

同时,浮点值也能够转换到Rational数值,例如:


julia> Rational(1.5)
3//2

julia> Rational(0.33333333333333)
6004799503160601//18014398509481984

julia> Rational(-2.5)
-5//2

julia> Rational(Inf)
1//0

julia> Rational(-Inf)
-1//0

其中,为何0.33333333333333转换的结果不是1//3而是由一大串数字构成的Rational类型对象,有兴趣的读者可以研究下。

如果要获得Rational对象的分子、分母部分,可以分别通过numerator()和denominator()函数实现,例如:


julia> numerator(2//3) 
2 
julia> denominator(2//3) 
3