在程式設計語言中,都有基本的數學運算和科學計算,它們常用的資料類型為整數和浮點數。
另外還有一個"字面量"的術語,字面量(literal)用于表達源代碼中一個固定值的表示法(notation),整數、浮點數以及字元串等等都是字面量。
例如:
a=1 // a 是變量,1 是整型字面量
b=1.0 // b 是變量,1.0 是浮點型字面量
Julia 提供了很豐富的原始數值類型,并基于它們定義了一整套算術運算操作,另外還提供按位運算符以及一些标準數學函數。
整數類型
下表列出來 Julia 支援的整數類型:
類型 | 帶符号? | 比特數 | 最小值 | 最大值 |
---|---|---|---|---|
Int8 | ✓ | 8 | -2^7 | 2^7 – 1 |
UInt8 | 2^8 – 1 | |||
Int16 | 16 | -2^15 | 2^15 – 1 | |
UInt16 | 2^16 – 1 | |||
Int32 | 32 | -2^31 | 2^31 – 1 | |
UInt32 | 2^32 – 1 | |||
Int64 | 64 | -2^63 | 2^63 – 1 | |
UInt64 | 2^64 – 1 | |||
Int128 | 128 | -2^127 | 2^127 – 1 | |
UInt128 | 2^128 – 1 | |||
Bool | N/A | false (0) | true (1) |
整數字面量形式:
執行個體
julia> 1
1
julia> 1234
1234
整型字面量的預設類型取決于目标系統是 32 位還是 64 位架構(目前大部分系統都是 64 位):
# 32 位系統:
julia> typeof(1)
# 64 位系統:
Julia 的内置變量 Sys.WORD_SIZE 表明了目标系統是 32 位還是 64 位架構:
julia> Sys.WORD_SIZE
Julia 也定義了 Int 與 UInt 類型,它們分别是系統有符号和無符号的原生整數類型的别名。
julia> Int
julia> UInt
溢出行為
在 Julia 裡,超出一個類型可表示的最大值會導緻環繞 (wraparound) 行為:
julia> x = typemax(Int64)
9223372036854775807
julia> x + 1
-9223372036854775808
julia> x + 1 == typemin(Int64)
true
是以,Julia 的整數算術實際上是模算數的一種形式,它反映了現代計算機實作底層算術的特點。在可能有溢出産生的程式中,對最值邊界出現循環進行顯式檢查是必要的。否則,推薦使用任意精度算術中的 BigInt 類型作為替代。
下面是溢出行為的一個例子以及如何解決溢出:
julia> 10^19
-8446744073709551616
julia> big(10)^19
10000000000000000000
除法錯誤
在以下兩種例外情況下,整數除法會觸發 DivideError 錯誤:
- 除以零
- 除以最小的負數
rem 取餘函數和 mod 取模函數在除零時抛出 DivideError 錯誤,執行個體如下:
julia> mod(1, 0)
ERROR: DivideError: integer division error
Stacktrace:
[1] div at .\int.jl:260 [inlined]
[2] div at .\div.jl:217 [inlined]
[3] div at .\div.jl:262 [inlined]
[4] fld at .\div.jl:228 [inlined]
[5] mod(::Int64, ::Int64) at .\int.jl:252
[6] top-level scope at REPL[52]:1
julia> rem(1, 0)
[1] rem(::Int64, ::Int64) at .\int.jl:261
[2] top-level scope at REPL[54]:1
浮點類型
下表列出來 Julia 支援的浮點類型:
精度 | ||
---|---|---|
Float16 | 半精度 | |
Float32 | 單精度 | |
Float64 | 雙精度 |
此外,對複數和有理數的完整支援是在這些原始資料類型之上建立起來的。
浮點數字面量格式表示如下,必要時可使用 E 來表示。
julia> 1.0
julia> 1.
julia> 0.5
0.5
julia> .5
julia> -1.23
-1.23
julia> 1e10
1.0e10
julia> 2.5e-4
0.00025
注:
在科學計數法中,為了使公式簡便,可以用帶 E 的格式表示。例如 1.03乘10的8次方,可簡寫為 "1.03E+08" 的形式,其中 "E" 是 exponent(指數) 的縮寫。
上面的結果都是 Float64 類型的值。使用 f 替代 e 可以得到 Float32 類型的字面量:
julia> x = 0.5f0
0.5f0
julia> typeof(x)
julia> 2.5f-4
0.00025f0
數值可以很容易地轉換為 Float32 類型:
julia> x = Float32(-1.5)
-1.5f0
也存在十六進制的浮點數字面量,但隻适用于 Float64 類型的值。一般使用 p 字首及以 2 為底的指數來表示:
julia> 0x1p0
julia> 0x1.8p3
12.0
julia> x = 0x.4p-1
0.125
Julia 也支援半精度浮點數(Float16),但它們是使用 Float32 進行軟體模拟實作的。
julia> sizeof(Float16(4.))
2
julia> 2*Float16(4.)
Float16(8.0)
下劃線 _ 可用作數字分隔符:
julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010
(10000, 5.0e-9, 0xdeadbeef, 0xb2)
浮點數中的零
浮點數有兩種零,正零和負零。它們互相相等但有着不同的二進制表示,可以使用 bitstring 函數來檢視:
julia> 0.0 == -0.0
julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
特殊的浮點值
有三種特定的标準浮點值不和實數軸上任何一點對應:
名稱 | 描述 | |||
---|---|---|---|---|
Inf16 | Inf32 | Inf | 正無窮 | 一個大于所有有限浮點數的數 |
-Inf16 | -Inf32 | -Inf | 負無窮 | 一個小于所有有限浮點數的數 |
NaN16 | NaN32 | NaN | 不是一個數 | 一個不和任何浮點值(包括自己)相等(==)的值 |
以下列舉了一些浮點數的運算執行個體:
julia> 1/Inf
0.0
julia> 1/0
julia> -5/0
julia> 0.000001/0
julia> 0/0
julia> 500 + Inf
julia> 500 - Inf
julia> Inf + Inf
julia> Inf - Inf
julia> Inf * Inf
julia> Inf / Inf
julia> 0 * Inf
julia> NaN == NaN
false
julia> NaN != NaN
julia> NaN < NaN
julia> NaN > NaN
我們還可以使用 typemin 和 typemax 函數:
julia> (typemin(Float16),typemax(Float16))
(-Inf16, Inf16)
julia> (typemin(Float32),typemax(Float32))
(-Inf32, Inf32)
julia> (typemin(Float64),typemax(Float64))
(-Inf, Inf)
機器精度
大多數實數都無法用浮點數準确地表示,是以有必要知道兩個相鄰可表示的浮點數間的距離,它通常被叫做機器精度。
Julia 提供了 eps 函數,它可以給出 1.0 與下一個 Julia 能表示的浮點數之間的內插補點:
julia> eps(Float32)
1.1920929f-7
julia> eps(Float64)
2.220446049250313e-16
julia> eps() # 與 eps(Float64) 相同
這些值分别是 Float32 中的 2.0^-23 和 Float64 中的 2.0^-52。eps 函數也可以接受一個浮點值作為參數,然後給出這個值與下一個可表示的浮點數值之間的絕對差。也就是說,eps(x) 産生一個和 x 類型相同的值,并且 x + eps(x) 恰好是比 x 更大的下一個可表示的浮點值:
julia> eps(1.0)
julia> eps(1000.)
1.1368683772161603e-13
julia> eps(1e-27)
1.793662034335766e-43
julia> eps(0.0)
5.0e-324
兩個相鄰可表示的浮點數之間的距離并不是常數,數值越小,間距越小,數值越大,間距越大。換句話說,可表示的浮點數在實數軸上的零點附近最稠密,并沿着遠離零點的方向以指數型的速度變得越來越稀疏。根據定義,eps(1.0) 與 eps(Float64) 相等,因為 1.0 是個 64 位浮點值。
Julia 也提供了 nextfloat 和 prevfloat 兩個函數分别傳回基于參數的下一個更大或更小的可表示的浮點數:
julia> x = 1.25f0
1.25f0
julia> nextfloat(x)
1.2500001f0
julia> prevfloat(x)
1.2499999f0
julia> bitstring(prevfloat(x))
"00111111100111111111111111111111"
julia> bitstring(x)
"00111111101000000000000000000000"
julia> bitstring(nextfloat(x))
"00111111101000000000000000000001"
這個例子展現了一般原則,即相鄰可表示的浮點數也有着相鄰的二進制整數表示。
舍入模式
一個數如果沒有精确的浮點表示,就必須被舍入到一個合适的可表示的值。
Julia 所使用的預設模式總是 RoundNearest,指舍入到最接近的可表示的值,這個被舍入的值會使用盡量少的有效位數。
julia> BigFloat("1.510564889",2,RoundNearest)
1.5
julia> BigFloat("1.550564889",2,RoundNearest)
julia> BigFloat("1.560564889",2,RoundNearest)
0 和 1 的字面量
Julia 提供了 0 和 1 的字面量函數,可以傳回特定類型或所給變量的類型。
函數 | |
---|---|
zero(x) | x 類型或變量 x 的類型的零字面量 |
one(x) | x 類型或變量 x 的類型的一字面量 |
這些函數在數值比較中可以用來避免不必要的類型轉換帶來的開銷。
julia> zero(Float32)
0.0f0
julia> zero(1.0)
julia> one(Int32)
julia> one(BigFloat)