整數(shù)和浮點數(shù)是算術(shù)和計算的基礎(chǔ)。它們都是數(shù)字文本。例如 1
是整數(shù)文本, 1.0
是浮點數(shù)文本。
Julia 提供了豐富的基礎(chǔ)數(shù)值類型,全部的算數(shù)運算符和位運算符,以及標(biāo)準(zhǔn)數(shù)學(xué)函數(shù)。這些數(shù)據(jù)和操作直接對應(yīng)于現(xiàn)代計算機支持的操作。因此, Julia 能充分利用硬件的計算資源。另外, Julia 還從軟件層面支持任意精度的算術(shù) ,可以用于表示硬件不能原生支持的數(shù)值,當(dāng)然,這犧牲了部分運算效率。
Julia 提供的基礎(chǔ)數(shù)值類型有:
Char
原生支持 Unicode 字符 ;詳見字符串 。
浮點數(shù)類型:
類型 | 精度 | 位數(shù) |
---|---|---|
Float16
|
半精度 | 16 |
Float32
|
單精度 | 32 |
Float64
|
雙精度 | 64 |
另外, 對復(fù)數(shù)和分?jǐn)?shù)的支持建立在這些基礎(chǔ)數(shù)據(jù)類型之上。所有的基礎(chǔ)數(shù)據(jù)類型通過靈活用戶可擴展的類型提升系統(tǒng)不需顯式類型轉(zhuǎn)換,就可以互相運算。
使用標(biāo)準(zhǔn)方式來表示文本化的整數(shù):
julia> 1
1
julia> 1234
1234
整數(shù)文本的默認(rèn)類型,取決于目標(biāo)系統(tǒng)是 32 位架構(gòu)還是 64 位架構(gòu):
# 32-bit system:
julia> typeof(1)
Int32
# 64-bit system:
julia> typeof(1)
Int64
Julia 內(nèi)部變量 `WORD_SIZE` 用以指示目標(biāo)系統(tǒng)是 32 位還是 64 位.
# 32-bit system:
julia> WORD_SIZE
32
# 64-bit system:
julia> WORD_SIZE
64
另外,Julia 定義了 Int
和 Uint
類型,它們分別是系統(tǒng)原生的有符號和無符號整數(shù)類型的別名:
# 32-bit system:
julia> Int
Int32
julia> Uint
Uint32
# 64-bit system:
julia> Int
Int64
julia> Uint
Uint64
對于不能用 32 位而只能用 64 位來表示的大整數(shù)文本,不管系統(tǒng)類型是什么,始終被認(rèn)為是 64 位整數(shù):
# 32-bit or 64-bit system:
julia> typeof(3000000000)
Int64
無符號整數(shù)的輸入和輸出使用前綴 0x
和十六進(jìn)制數(shù)字 0-9a-f
(也可以使用 A-F
)。無符號數(shù)的位數(shù)大小,由十六進(jìn)制數(shù)的位數(shù)決定:
julia> 0x1
0x01
julia> typeof(ans)
Uint8
julia> 0x123
0x0123
julia> typeof(ans)
Uint16
julia> 0x1234567
0x01234567
julia> typeof(ans)
Uint32
julia> 0x123456789abcdef
0x0123456789abcdef
julia> typeof(ans)
Uint64
二進(jìn)制和八進(jìn)制文本:
julia> 0b10
0x02
julia> typeof(ans)
Uint8
julia> 0o10
0x08
julia> typeof(ans)
Uint8
基礎(chǔ)數(shù)值類型的最小值和最大值,可由 typemin
和 typemax
函數(shù)查詢:
julia> (typemin(Int32), typemax(Int32))
(-2147483648,2147483647)
julia> for T = {Int8,Int16,Int32,Int64,Int128,Uint8,Uint16,Uint32,Uint64,Uint128}
println("$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]")
end
Int8: [-128,127]
Int16: [-32768,32767]
Int32: [-2147483648,2147483647]
Int64: [-9223372036854775808,9223372036854775807]
Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]
Uint8: [0,255]
Uint16: [0,65535]
Uint32: [0,4294967295]
Uint64: [0,18446744073709551615]
Uint128: [0,340282366920938463463374607431768211455]
typemin
和 typemax
的返回值,與所給的參數(shù)類型是同一類的。(上述例子用到了一些將要介紹到的特性,包括 for 循環(huán) ,字符串 ,及內(nèi)插 。)
在 Julia 中,如果計算結(jié)果超出數(shù)據(jù)類型所能代表的最大值,將會發(fā)生溢出:
julia> x = typemax(Int64)
9223372036854775807
julia> x + 1
-9223372036854775808
julia> x + 1 == typemin(Int64)
true
可見, Julia 中的算數(shù)運算其實是一種同余算術(shù) 。它反映了現(xiàn)代計算機底層整數(shù)算術(shù)運算特性。如果有可能發(fā)生溢出,一定要顯式的檢查是否溢出;或者使用 BigInt
類型(詳見任意精度的算術(shù) )。
為了減小溢出所帶來的影響,整數(shù)加減法、乘法、指數(shù)運算都會把原先范圍較小的整數(shù)類型提升到 Int
或 Uint
類型。(除法、求余、位運算則不提升類型)。
除法錯誤
整數(shù)除法(div
功能)有兩個額外的樣例:被 0 除,和被最低的負(fù)數(shù)(typemin
)-1 除。兩個例子都拋出了一個 DivideError
。余數(shù)和模運算(rem
和 mod
)當(dāng)它們的第二個參數(shù)為 0 時,拋出了一個 DivideError
。
浮點數(shù)
使用標(biāo)準(zhǔn)格式來表示文本化的浮點數(shù):
julia> 1.0
1.0
julia> 1.
1.0
julia> 0.5
0.5
julia> .5
0.5
julia> -1.23
-1.23
julia> 1e10
1.0e10
julia> 2.5e-4
0.00025
上述結(jié)果均為 Float64
值。文本化的 Float32
值也可以直接輸入,這時使用 f
來替代 e
:
julia> 0.5f0
0.5f0
julia> typeof(ans)
Float32
julia> 2.5f-4
0.00025f0
浮點數(shù)也可以很容易地轉(zhuǎn)換為 Float32
:
julia> float32(-1.5)
-1.5f0
julia> typeof(ans)
Float32
十六進(jìn)制浮點數(shù)的類型,只能為 Float64
:
julia> 0x1p0
1.0
julia> 0x1.8p3
12.0
julia> 0x.4p-1
0.125
julia> typeof(ans)
Float64
Julia 也支持半精度浮點數(shù)(Float16
) ,但只用來存儲。計算時,它們被轉(zhuǎn)換為 Float32
:
julia> sizeof(float16(4.))
2
julia> 2*float16(4.)
8.0f0
浮點數(shù)類型中存在兩個零 ,正數(shù)的零和負(fù)數(shù)的零。它們相等,但有著不同的二進(jìn)制表示,可以使用 bits
函數(shù)看出:
julia> 0.0 == -0.0
true
julia> bits(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"
julia> bits(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"
有三個特殊的標(biāo)準(zhǔn)浮點數(shù):
特殊值 | 名稱 | 描述 | ||
Float16 | Float32 | Float64 | ||
Inf16 | Inft32 | Inf | 正無窮 | 比所有的有限的浮點數(shù)都大 |
-Inf16 | -Inft32 | -Inf | 負(fù)無窮 | 比所有的有限的浮點數(shù)都小 |
NaN16 | NaN32 | NaN | 不存在 | 不能和任意浮點數(shù)比較大小(包括它自己) |
詳見數(shù)值比較 。按照 IEEE 754 標(biāo)準(zhǔn) ,這幾個值可如下獲得:
julia> 1/Inf
0.0
julia> 1/0
Inf
julia> -5/0
-Inf
julia> 0.000001/0
Inf
julia> 0/0
NaN
julia> 500 + Inf
Inf
julia> 500 - Inf
-Inf
julia> Inf + Inf
Inf
julia> Inf - Inf
NaN
julia> Inf * Inf
Inf
julia> Inf / Inf
NaN
julia> 0 * Inf
NaN
typemin
和 typemax
函數(shù)也適用于浮點數(shù)類型:
julia> (typemin(Float16),typemax(Float16))
(-Inf16,Inf16)
julia> (typemin(Float32),typemax(Float32))
(-Inf32,Inf32)
julia> (typemin(Float64),typemax(Float64))
(-Inf,Inf)
大多數(shù)的實數(shù)并不能用浮點數(shù)精確表示,因此有必要知道兩個相鄰浮點數(shù)間的間距,也即計算機的精度。
Julia 提供了 eps
函數(shù),可以用來檢查 1.0
和下一個可表示的浮點數(shù)之間的間距:
julia> eps(Float32)
1.1920929f-7
julia> eps(Float64)
2.220446049250313e-16
julia> eps() # same as eps(Float64)
2.220446049250313e-16
eps
函數(shù)也可以取浮點數(shù)作為參數(shù),給出這個值和下一個可表示的浮點數(shù)的絕對差,即,eps(x)
的結(jié)果與 x
同類型,且滿足 x + eps(x)
是下一個比 x
稍大的、可表示的浮點數(shù):
julia> eps(1.0)
2.220446049250313e-16
julia> eps(1000.)
1.1368683772161603e-13
julia> eps(1e-27)
1.793662034335766e-43
julia> eps(0.0)
5.0e-324
相鄰的兩個浮點數(shù)之間的距離并不是固定的,數(shù)值越小,間距越??;數(shù)值越大, 間距越大。換句話說,浮點數(shù)在 0
附近最稠密,隨著數(shù)值越來越大,數(shù)值越來越稀疏,數(shù)值間的距離呈指數(shù)增長。根據(jù)定義, eps(1.0)
與 eps(Float64)
相同,因為 1.0
是 64
位浮點數(shù)。
函數(shù) nextfloat
和 prevfloat
可以用來獲取下一個或上一個浮點數(shù):
julia> x = 1.25f0
1.25f0
julia> nextfloat(x)
1.2500001f0
julia> prevfloat(x)
1.2499999f0
julia> bits(prevfloat(x))
"00111111100111111111111111111111"
julia> bits(x)
"00111111101000000000000000000000"
julia> bits(nextfloat(x))
"00111111101000000000000000000001"
此例顯示了鄰接的浮點數(shù)和它們的二進(jìn)制整數(shù)的表示。
如果一個數(shù)沒有精確的浮點數(shù)表示,那就需要舍入了??梢愿鶕?jù) IEEE 754 標(biāo)準(zhǔn) 來更改舍入的模型:
julia> 1.1 + 0.1
1.2000000000000002
julia> with_rounding(Float64,RoundDown) do
1.1 + 0.1
end
1.2
默認(rèn)舍入模型為 RoundNearest
,它舍入到最近的可表示的值,這個被舍入的值使用盡量少的有效數(shù)字。
浮點數(shù)的算術(shù)運算同人們的預(yù)期存在著許多差異,特別是對不了解底層實現(xiàn)的人。許多科學(xué)計算的書籍都會詳細(xì)的解釋這些差異。下面是一些參考資料:
為保證整數(shù)和浮點數(shù)計算的精度,Julia 打包了 GNU Multiple Precision Arithmetic Library, GMP(https://gmplib.org/) 和 GNU MPFR Library。Julia 相應(yīng)提供了 BigInt
和 BigFloat
類型。
可以通過基礎(chǔ)數(shù)值類型或 String
類型來構(gòu)造:
julia> BigInt(typemax(Int64)) + 1
9223372036854775808
julia> BigInt("123456789012345678901234567890") + 1
123456789012345678901234567891
julia> BigFloat("1.23456789012345678901")
1.234567890123456789010000000000000000000000000000000000000000000000000000000004e+00 with 256 bits of precision
julia> BigFloat(2.0^66) / 3
2.459565876494606882133333333333333333333333333333333333333333333333333333333344e+19 with 256 bits of precision
julia> factorial(BigInt(40))
815915283247897734345611269596115894272000000000
然而,基礎(chǔ)數(shù)據(jù)類型和 BigInt/BigFloat 不能自動進(jìn)行類型轉(zhuǎn)換,需要明確指定:
julia> x = typemin(Int64)
-9223372036854775808
julia> x = x - 1
9223372036854775807
julia> typeof(x)
Int64
julia> y = BigInt(typemin(Int64))
-9223372036854775808
julia> y = y - 1
-9223372036854775809
julia> typeof(y)
BigInt (constructor with 10 methods)
BigFloat 運算的默認(rèn)精度(有效數(shù)字的位數(shù))和舍入模型,是可以改的。然后,計算就都按照更改之后的設(shè)置來運行了:
julia> with_rounding(BigFloat,RoundUp) do
BigFloat(1) + BigFloat("0.1")
end
1.100000000000000000000000000000000000000000000000000000000000000000000000000003e+00 with 256 bits of precision
julia> with_rounding(BigFloat,RoundDown) do
BigFloat(1) + BigFloat("0.1")
end
1.099999999999999999999999999999999999999999999999999999999999999999999999999986e+00 with 256 bits of precision
julia> with_bigfloat_precision(40) do
BigFloat(1) + BigFloat("0.1")
end
1.1000000000004e+00 with 40 bits of precision
Julia 允許在變量前緊跟著數(shù)值文本,來表示乘法。這有助于寫多項式表達(dá)式:
julia> x = 3
3
julia> 2x^2 - 3x + 1
10
julia> 1.5x^2 - .5x + 1
13.0
指數(shù)函數(shù)也更好看:
julia> 2^2x
64
數(shù)值文本系數(shù)同單目運算符一樣。因此 2^3x
被解析為 2^(3x)
, 2x^3
被解析為 2*(x^3)
。
數(shù)值文本也可以作為括號表達(dá)式的因子:
julia> 2(x-1)^2 - 3(x-1) + 1
3
括號表達(dá)式可作為變量的因子:
julia> (x-1)x
6
不要接著寫兩個變量括號表達(dá)式,也不要把變量放在括號表達(dá)式之前。它們不能被用來指代乘法運算:
julia> (x-1)(x+1)
ERROR: type: apply: expected Function, got Int64
julia> x(x+1)
ERROR: type: apply: expected Function, got Int64
這兩個表達(dá)式都被解析為函數(shù)調(diào)用:任何非數(shù)值文本的表達(dá)式,如果后面跟著括號,代表調(diào)用函數(shù)來處理括號內(nèi)的數(shù)值(詳見函數(shù))。因此,由于左面的值不是函數(shù),這兩個例子都出錯了。
需要注意,代數(shù)因子和變量或括號表達(dá)式之間不能有空格。
文本因子與兩個數(shù)值表達(dá)式語法沖突: 十六進(jìn)制整數(shù)文本和浮點數(shù)文本的科學(xué)計數(shù)法:
0xff
可以被解析為數(shù)值文本 0
乘以變量 xff
1e10
可以被解析為數(shù)值文本 1
乘以變量 e10
。E
格式也同樣。這兩種情況下,我們都把表達(dá)式解析為數(shù)值文本:
0x
開頭的表達(dá)式,都被解析為十六進(jìn)制文本e
或 E
,都被解析為浮點數(shù)文本Julia 提供了一些函數(shù), 用以得到特定數(shù)據(jù)類型的零和一文本。
?函數(shù) | 說明 |
---|---|
zero(x)
|
類型 x 或變量 x 的類型下的文本零 |
one(x) | ?類型x ?或?變量x ? 的類型下的文本一 |
這倆函數(shù)在數(shù)值比較中可用來避免額外的類型轉(zhuǎn)換 。
例如:
julia> zero(Float32)
0.0f0
julia> zero(1.0)
0.0
julia> one(Int32)
1
julia> one(BigFloat)
1e+00 with 256 bits of precision
更多建議: