可以看到,Complex
是一个参数化的类型。因为在其名称的右侧还有一个由花括号包裹的类型参数。这个类型参数会是一个代表了某个类型的标识符。关于参数化类型,我们在下下一章就会讲到。
为了使常见的数学公式和表达式更加清晰,Julia 允许在变量之前紧挨一个数值字面量,以表示两个数相乘。比如,如果变量x
的值是整数8
,那么2x^3
就表示2
乘以8
的3
次方。又比如,2^3x
表示2
的24
次方。在这种情况下,变量x
就被称为数值字面量系数(numeric literal coefficient)。
正因为如此,我们才需要特别注意,上例中的2im
和2.2im
虽然看起来与这种表示法非常相似,但其含义却是完全不同的。整数或浮点数的字面量与常量im
共同组成的是一个复数的虚部。而且还要注意,在构造复数的虚部时,我们就不能再使用数值字面量系数了。因为这肯定会产生歧义。比如,1 + 2xim
就是不合法的,除非已经存在一个名为xim
的变量,但如此一来这表示的就不是一个复数了。如果必须有变量参与复数的构造,那么我们可以使用complex
函数,例如:complex(1, 2x)
。
Julia 允许复数参与标准的数学运算。所以,下面的这些数学表达式是合法的:
julia> (1 + 2im) + (3 + 4im)
4 + 6im
-2 - 2im
julia> (1 + 2im) * (3 + 4im)
-5 + 10im
julia> (1 + 2im) / (3 + 4im)
julia> 3(1 + 2im)^8
-1581 + 1008im
julia>
要想分别得到一个复数的实部和虚部,我们就需要调用real
函数和imag
函数。示例如下:
另外,我们还可以利用conj
函数求出一个复数的共轭(conjugate),以及使用abs
函数计算出一个复数与0
之间的距离,等等。总之,Julia 预定义的很多数学函数都可以应用于复数。
5.4.2 有理数
我们在前面说过,浮点数无法精确地表示所有小数。比如,1/3
是一个无限循环小数,但用浮点数表示的话只能是这样的:
julia> 1/3
0.3333333333333333
julia> typeof(ans)
Float64
julia>
严格来说,1/3
并不是一个浮点数。因为浮点数会对无限循环小数做舍入,这会损失精度。但是,它肯定是一个有理数。
在操作符//
左侧的被称为分子,而在它右侧的被称为分母。注意,这两个数都只能是整数,而不能是浮点数。
如果在分子和分母之间存在公因数,那么 Julia 会自动地把它们化为最小项并让分母变为非负整数。例如:
1//3
julia> 3//-9
-1//3
julia> 42//126
1//3
julia>
函数numerator
和denominator
可以让我们分别得到一个有理数的分子和分母:
有理数可以参与标准的数学运算。比如,我们可以拿一个有理数与一个整数、浮点数或者其他有理数进行比较。又比如,我们可以对有理数进行加减乘数等运算。另外,有理数也可以很容易地被转换为浮点数。例如:
julia> float(1//3)
0.3333333333333333
最后,需要我们注意的是,0//0
是不合法的。该字面量会引发一个错误。相应的,表示浮点数的字面量0/0
等同于。从技术标准的角度讲,NaN
不与任何东西(包括它自己)相等。