天天看點

Julia 資料類型

在程式設計語言中,都有基本的數學運算和科學計算,它們常用的資料類型為整數和浮點數。

另外還有一個"字面量"的術語,字面量(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)