鍍金池/ 教程/ Java/ 整數(shù)和浮點數(shù)
類型轉(zhuǎn)換和類型提升
方法
嵌入式 Julia
交互
調(diào)用 C 和 Fortran 代碼
類型
代碼性能優(yōu)化
多維數(shù)組
元編程
函數(shù)
簡介
線性代數(shù)
與其它語言的區(qū)別
數(shù)學(xué)運(yùn)算和基本函數(shù)
構(gòu)造函數(shù)
控制流
常見問題
并行計算
擴(kuò)展包
開發(fā)擴(kuò)展包
開始
字符串
運(yùn)行外部程序
變量的作用域
模塊
網(wǎng)絡(luò)和流
代碼樣式
復(fù)數(shù)和分?jǐn)?shù)
可空類型
整數(shù)和浮點數(shù)
變量
日期和時間

整數(shù)和浮點數(shù)

整數(shù)和浮點數(shù)是算術(shù)和計算的基礎(chǔ)。它們都是數(shù)字文本。例如 1 是整數(shù)文本, 1.0 是浮點數(shù)文本。

Julia 提供了豐富的基礎(chǔ)數(shù)值類型,全部的算數(shù)運(yùn)算符和位運(yùn)算符,以及標(biāo)準(zhǔn)數(shù)學(xué)函數(shù)。這些數(shù)據(jù)和操作直接對應(yīng)于現(xiàn)代計算機(jī)支持的操作。因此, Julia 能充分利用硬件的計算資源。另外, Julia 還從軟件層面支持任意精度的算術(shù) ,可以用于表示硬件不能原生支持的數(shù)值,當(dāng)然,這犧牲了部分運(yùn)算效率。

Julia 提供的基礎(chǔ)數(shù)值類型有:

  • 整數(shù)類型

Char 原生支持 Unicode 字符 ;詳見字符串 。

浮點數(shù)類型:

類型 精度 位數(shù)
Float16 半精度 16
Float32 單精度 32
Float64 雙精度 64

另外, 對復(fù)數(shù)和分?jǐn)?shù)的支持建立在這些基礎(chǔ)數(shù)據(jù)類型之上。所有的基礎(chǔ)數(shù)據(jù)類型通過靈活用戶可擴(kuò)展的類型提升系統(tǒng)不需顯式類型轉(zhuǎn)換,就可以互相運(yùn)算。

整數(shù)

使用標(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 定義了 IntUint 類型,它們分別是系統(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ù)值類型的最小值和最大值,可由 typemintypemax 函數(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]

typemintypemax 的返回值,與所給的參數(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ù)運(yùn)算其實是一種同余算術(shù) 。它反映了現(xiàn)代計算機(jī)底層整數(shù)算術(shù)運(yùn)算特性。如果有可能發(fā)生溢出,一定要顯式的檢查是否溢出;或者使用 BigInt 類型(詳見任意精度的算術(shù) )。

為了減小溢出所帶來的影響,整數(shù)加減法、乘法、指數(shù)運(yùn)算都會把原先范圍較小的整數(shù)類型提升到 IntUint 類型。(除法、求余、位運(yùn)算則不提升類型)。

除法錯誤

整數(shù)除法(div 功能)有兩個額外的樣例:被 0 除,和被最低的負(fù)數(shù)(typemin)-1 除。兩個例子都拋出了一個 DivideError。余數(shù)和模運(yùn)算(remmod)當(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ù)類型中存在兩個零 ,正數(shù)的 零和負(fù)數(shù)的零。它們相等,但有著不同的二進(jìn)制表示,可以使用 bits 函數(shù)看出:

julia> 0.0 == -0.0
true

julia> bits(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"

julia> bits(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"

特殊的浮點數(shù)

有三個特殊的標(biāo)準(zhǔn)浮點數(shù):

特殊值 名稱 描述
Float16 Float32 Float64
Inf16 Inft32 Inf 正無窮 比所有的有限的浮點數(shù)都大
-Inf16 -Inft32 -Inf 負(fù)無窮 比所有的有限的浮點數(shù)都小
NaN16 NaN32 NaN 不存在 不能和任意浮點數(shù)比較大?。òㄋ约海?/td>

詳見數(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

typemintypemax 函數(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ù)間的間距,也即計算機(jī)的精度

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.064 位浮點數(shù)。

函數(shù) nextfloatprevfloat 可以用來獲取下一個或上一個浮點數(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ùn)算同人們的預(yù)期存在著許多差異,特別是對不了解底層實現(xiàn)的人。許多科學(xué)計算的書籍都會詳細(xì)的解釋這些差異。下面是一些參考資料:

任意精度的算術(shù)

為保證整數(shù)和浮點數(shù)計算的精度,Julia 打包了 GNU Multiple Precision Arithmetic Library, GMP(https://gmplib.org/) 和 GNU MPFR Library (http://www.mpfr.org/)。Julia 相應(yīng)提供了 BigIntBigFloat 類型。

可以通過基礎(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 運(yùn)算的默認(rèn)精度(有效數(shù)字的位數(shù))和舍入模型,是可以改的。然后,計算就都按照更改之后的設(shè)置來運(yùn)行了:

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

代數(shù)系數(shù)

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ù)同單目運(yùn)算符一樣。因此 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á)式之前。它們不能被用來指代乘法運(yùn)算:

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ù)法:

  • 十六進(jìn)制整數(shù)文本表達(dá)式 0xff 可以被解析為數(shù)值文本 0 乘以變量 xff
  • 浮點數(shù)文本表達(dá)式 1e10 可以被解析為數(shù)值文本 1 乘以變量 e10 。E 格式也同樣。

這兩種情況下,我們都把表達(dá)式解析為數(shù)值文本:

  • 0x 開頭的表達(dá)式,都被解析為十六進(jìn)制文本
  • 以數(shù)字文本開頭,后面跟著 eE ,都被解析為浮點數(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
上一篇:代碼樣式下一篇:字符串