二、變數與資料型別

愛碼者發表於2020-10-12

一、變數

在Julia中的一個變數是一個與一個值關聯(或繫結)的名稱。它的作用變現在當你想儲存一個值(例如,你在進行一些數學運算後得到了一些值,你需要在之後使用到這些值)時。

變數就是給資料提供一個記憶體標識的符號。

變數的命名規範:

  • 變數名使用小寫字母
  • 單詞之間使用下劃線(’_’)分割,但是不鼓勵使用
  • 型別名首字母大寫,單詞之間使用駝峰式分隔
  • 函式名和巨集名使用小寫字母,不使用下劃線分割單詞。
  • 修改引數的函式結尾使用 ! . 這樣的函式被稱為mutating functions 或 in-place functions

二、資料型別

使用內建函式 typemin(型別)typemax(型別) 來獲得該型別能夠表達的數值範圍。

使用內建函式 typeof(),在任何時候檢視某個值或變數等任意物件的型別。

2.1 整型

整型又分成有符號無符號兩類,其中的有符號型能夠表達負數而無符號型僅用於表達正數。

無符號比有符號表達的正數範圍要大。

image-20201010145202336

0x表示十六進位制數

0b表示二進位制數

0o表示八進位制數

1、型別強制限定

格式: 型別名稱(輸入值或變數)

示例:x2 = Int32(20) 或 x3 = Int64(a)

2、有無符號轉換

有符號轉為無符號:unsigned() 示例:unsigned(Int16(20))

無符號轉為有符號:signed() 示例:signed(UInt32(20))

注意點:

  • unsigned()函式會忽略負值的檢查
  • signed()會忽略表達範圍越界(Overflow,溢位)的情況。這種情況並不會上報異常,因此在實踐中需要多多留意。

2.2 布林型

可以通過bitstring()函式檢視一下true及false的記憶體表達方式。

檢視的最終結果類似於型別Int8的1和0這兩個值。

型別定義:

  • Bool(1):true

  • Bool(0):false

注意點:

在Julia中的布林型是整型的一種,但不能將整型當布林型使用,因為它們在設計機制和使用約束上有著許多差異,這是與其他語言不同的地方。

2.3 浮點型

image-20201010152815784

以下幾種形式都是正確的:

  • 正數:1.0
  • 省略小數部分:1.
  • 省略整數部分:.5
  • 負數:-1.25
  • 科學計數法:2.5e-4

注意點:

  • 64位系統預設會選擇Float64型別
  • Float16一般不使用,即使你顯示的進行型別限定,參與計算時也會被處理為Float32型別

1、零的表達

浮點型在表達數值零時有些特別,存在正零和負零兩種情況,因為它們的記憶體表達是不相同的。

Julia提供了專門的函式用於生成某型別的零值:zero()

Julia也提供了專門的函式用於生成各型別的1值:one()

2、epsilon

計算機中相鄰兩個浮點型值之間存在著“縫隙”,因此,會存在誤差,影響著科學計算的精度。為了能夠評估這種誤差,相鄰浮點值間這種縫隙的寬度被稱為epsilon值。

使用函式**eps()**可以檢視某個浮點值附近的epsilon值。

內建的nextfloat()與prefloat()函式可以分別獲得某個浮點值的後繼與前繼浮點值。

結論:

隨浮點值(絕對值)從大到小,epsilon值會呈指數級驟減,到零值處最小。epsilon值得大小關於零點對稱,與浮點值的正負無關。

3、無窮值

image-20201010162211427

不論是正無窮大還是負無窮小,Julia中定義的無窮值都不是一種型別,而是浮點型的數值常量。

Julia有了對無窮值的支援,Julia中的浮點運算就可以正常地使用除零操作了。

如:julia> 1.2 / 0 = Inf

如何判斷某個變數或值是否是無窮值,可通過**isfinite()isinf()**函式進行判斷。

4、非數值

非數值(Not-a-Number)是Julia另外定義了一組特殊的浮點值常量。

非數值代表的是無效的浮點值,需要標記它的存在。

定義的三種浮點型別:

image-20201010163635801

可以使用函式 isnan() 來檢驗一個變數或數值是否為“非數值”。

5、內建常量

Julia在模組Base.MathConstants模組中定義了常見的數學或物理等方面的係數常量。

常用的內建變數如下圖所示:

image-20201010164321907

使用內建變數需要匯入模組Base.MathConstants

如:julia> using Base.MathConstants

這些常用變數並不是浮點型別,而是內部定義的無理數型別(Irrational)

Irrational的父型別是AbstractIrrational型。

可以使用函式typeof(pi)進行檢視。

2.4 有理數型

型別名(Rational)

Rational型別是Julia中特有的,以“分子 // 分母”格式表達。其中雙斜線並非是運算子,而是表達有理數結構的特定操作符。

由於對無窮值的支援,所以在Rational物件中允許分母為0,但不允許分子和分母同時為0。

image-20201010170358766

Rational型別的有理數值均可轉換為浮點值:

image-20201010170916223

浮點值也能夠轉換到Rational數值:

image-20201010170937785

通過**numerator()denominator()**函式可以獲得Rational物件的分子、分母部分。

2.5 複數型

image-20201010173234609

其中,Number是抽象型別,表示Complex是數值型別的一種;而{T<:Real}表示實部與虛部的型別T可以是Real型別的任一種,包括各種浮點型、整數型、有理數Rational型及無理數AbstractIrrational型(Irrational的父型別)等。

特別地,當T取Float16、Float32及Float64時,對應的複數型分別為Complex{Float16}、Complex{Float32}及Complex{Float64}。為了方便,Julia為它們提供了別名,即ComplexF16、ComplexF32和ComplexF64。

在建立Complex數值物件時,也可以像整型、浮點型、有理數型那樣以字面值的方式提供,格式為“實部 + 虛部im”,其中的虛部標識採用了im,對應於數學中的虛部單位i.

在使用複數型表示式時,如果虛部是變數不建議使用 * 號進行書寫,如下所示:

julia > a=1;b=2
julia > a + b * im
1 + 2im

推薦使用函式**complex()**進行:

julia> complex(a,b)

也可以使用複數型別宣告的構造方法建立Complex型別:

julia > ComplexF32(1.0, 2.0)

針對複數的各種操作,Julia提供了各種函式:

image-20201010175756791

2.6 隨機數

馬特賽特旋轉演演算法是Julia預設採用的方法,用於製作偽隨機數。

三種常見的隨機數生成方法:

  • 均勻分佈隨機數

    函式rand()用於生成均勻分佈的隨機數。對於浮點型別來說,該函式生成的隨機數所處的區間是[0, 1),即小於1大於等於0的浮點數。

  • 正態分佈隨機數

    函式randn()則是用於生成均值為0,方差為1的正態分佈中的隨機數。

  • 指數分佈隨機數

    函式randexp()用於生成符合指數分佈的隨機數。需要匯入模組Random

image-20201010181828652

2.7 任意精度算術

在進行“超大”值進行運算時,會發生越界溢位的情況。針對此現象,Julia封裝了GUN的多精度算術庫和多精度浮點計算庫,提供了BigIntBigFloat兩個型別。

BigInt是Integer型別的一種。

BigFloat是浮點型AbstractFloat(浮點數抽象型別)的一種。

兩個常用函式:

  • parse()函式:將字串轉為數值型別
  • big()函式:將不同型別的“超大”數值轉為BigInt或BigFloat型別。

一種字面值的表達方式:

​ Julia特有的下劃線分割方式,便於視覺上的劃分。其中下劃線的位置並沒有明確的限制,而且與資料型別無關。

​ 10_000_000 = 10000000

image-20201010183602599

2.8 字串

2.8.1 字元

字元是一種Char型別,是一個32位儲存結構的元型別,父型別為AbstractChar抽象型別。

使用方式: ’ 單個字元’

幾種使用情況:

  • 可以使用Unicode碼值建立字元物件,只需要以\u 或者 \U 作為字首輸入其十六位碼值即可。
  • 使用Char的建構函式建立字元物件,Char()
  • 有的Unicode碼值未必有有效的字元,可以使用**isvalid()**函式進行檢查
  • Julia允許將字元轉換到Number型別的任意一個具體子型別,使用**convert()**函式即可。

2.8.2 String物件

字串在Julia中是String型別,它的父型別是AbstractString。

AbstractString的字串物件是不可變的,和java是一樣的。

如何使用?

需使用成對的雙引號或三組雙引號表示。如:“aaa” “”“bbb”""

如果字串中含有雙引號,使用雙引號時需要用反斜槓進行轉義,使用三組雙引號則不需要轉義。

換行符的三種方式:

CR、CRLF、LF,一般分別以\r , \r\n 及 \n表示。

1、索引

在Julia中,字串也是有索引概念的,通過索引方式取得其中任意位置的字元。

需要注意的是:Julia的索引下標是從1開始,而在java中是從0開始。

end關鍵字可以表示字串索引的最後一位,而且還可以通過表示式進行計算。

同樣,如果索引越界,會報越界異常BoundError。

image-20201012100046275

關於字串中存在Unicode字元問題:

  • 由於Unicode字元是可變寬的編碼方式,因此,位元組數是不一樣的。
  • 通過nextind(str::AbstractString, i::Integer, n::Integer=1) -> Int函式獲取字串中字元的索引值。

image-20201012100846357

prevind()函式和nextind()函式類似,前者是從後往前,相反,後者是從前往後獲取下標值。

給出字串最大索引值的兩個函式:

  • lastindex()函式是按照位元組移動
  • length()函式是按照字元個數

因此,兩個函式獲取的值是不同的。

image-20201012102016062

2、遍歷

對於字串的遍歷,我們只需要知道如何解決包含Unicode字元的字串的問題。

通過函式**length()和lastindex()**都不能遍歷含有Unicode字元的字串。

如何解決呢?

Julia提供了函式**eachindex()**函式,可以獲得相應的索引值和字元。

字串也是可迭代數集的一種,可以基於迭代器,採用元素迭代的方式進行遍歷(Julia推薦)。

因為迭代器方式,可以適用於字串的任何情況(包括含有Unicode),也是最方便、簡潔的方式。

迭代器的兩種語法如下

第一種:

for i in str
    ...
end

第二種:

for i ∈ str
    ...
end

image-20201012110613500

3、子串

子串指的是從一個字串中擷取出來的一個字串。

擷取的方式是根據索引範圍擷取。

格式:

str[初始值:邊界值]

使用範圍索引需要注意以下幾條:

  • 範圍索引使用的閉區間,故“初始值”與“邊界值”對應位置的元素都會取出。
  • 如果初始值大於邊界值,結果將會是空字串。
  • 如果初始值等於邊界值,取出的將是僅有一個字元的字串,但不是字元。

2.8.3 變數替換

在Julia字串中,美元符號 $ 是一個特殊的字元,用於表示緊隨其後的是一個表示式或者變數名。

使用格式:

"$變數名"
"$(表示式)"

如果字串中包含$,但是不代表表示式或者變數名,需要使用轉義字元進行轉義。

image-20201012121929797

2.8.4 正規表示式

在Julia中,正規表示式為Regex型別。

由於Regex的父型別不是AbstractString型別,它被視為一種非標準字串。因此,對字串的一些操作對正規表示式並不適用,包括索引、遍歷、子串等。

如何定義一個正規表示式物件?

  • 在常規字串上加入字首 r 作為標識 如:a = r"^\s*(?:#|$)"
  • 使用構造方法Regex()從一個字串定義一個正規表示式物件 如:Regex("^\\s*(?:#|\$)")

1、匹配

匹配指在某個字串中查詢是否存在一個或多個子串,能夠符合正規表示式物件定義的字元構成模式

使用函式 occursin() 可以實現。

函式原型:occursin(r::Regex, s::AbstractString) -> Bool

示例:

occursin(r"^\s*(?:#|$)", "not a comment")

2、提取

提取是指將滿足正則模式的多個子串內容從原字串中單獨拿出來,並能夠給出每個子串的位置。

通過Julia內建的**match()函式或eachmatch()**函式遍可達到這些目的,而提取的資訊會儲存在型別名為RegexMatch的物件中。

通過dump()函式可檢視此物件的內部結構:

image-20201012144231473

每個成員變數(有使用場景)的意義如下:

  • 欄位match記錄匹配的子串整體內容
  • 欄位offset記錄匹配的子串整體在原字串中的偏移
  • 欄位captures記錄捕捉到的各分組子串內容,即match欄位中的字串裡符合圓括號內正規表示式的子串,相當於正則模式中對應的各個組(Group);若捕捕捉結果為空,該欄位將為nothing,而offsets值會為0(無效值)
  • 欄位offsets記錄捕捉到的各分組子串的偏移
  • 欄位regex記錄原始正規表示式的內容

示例:

image-20201012150351397

2.8.5 常用操作

1、連線

字串連線的幾種方法:

  • String建構函式。不支援元組結構和字串陣列建立。
  • join()函式。不要直接將待連線內容以獨立字串或字元引數的形式傳入,否則會得到不可預期的結果。
  • string()函式。直接將結構轉為字串,而不是將內部結構進行連線。
  • * :將字串或者字元進行前後連線。
  • broadcast()函式。實現多個字串的連線。必須帶 ***** 號,如:broadcast(*, “abc”, “ert”)

輔助函式:repeat(),可以構造內容重複出現的字串。

2、比較

字串和字串,字元與字元是可以進行大小比較的。

字串與字元是不可以進行大小比較的,但是,字串和字元是可以進行,!=,== ,===的。因為,是否相等或是否相同運算子本身就不限定運算元的型別。

image-20201012154340540

3、搜尋

  • occursin()函式,判斷一個字串是否是另一個字串的子串。也適用於Char物件 如:occursin(“a”,“abc”)
  • in()函式,判斷一個字元是否屬於某個字串(上一個也可以做到)
    • 也可以使用in斷言 如:‘a’ in “abc”
    • 也可以使用 ∈ 如:‘a’ ∈ “abc”

從前往後搜尋的兩個函式:

  • findfirst()
  • findlast()

指定搜尋的起始位置的兩個函式:

  • findnext()
  • findprev()

4、替換

replace(字串,字串中的字元=>新的字元,[count=val])

count可以設定被替換的個數。

新的字元可以使用正規表示式進行表示。

image-20201012161525381

uppercase()函式,轉為大寫。

5、分割

split()函式用於字串的分割,和java中的是一樣的。

image-20201012162515948

2.8.6 位元組陣列

位元組陣列的型別是Array{UInt8, 1}。

如何將字串解析為位元組陣列?

  • 在字串前加一個b 如:b"abc"

如何將字串物件轉為位元組陣列?

  • Array{UInt8, 1}(s) : s是字串物件
  • 使用convert()函式。 如:convert(Array{UInt8, 1}, “bytes”)

將字串轉為位元組陣列的過程中,Julia遵循以下的轉換規則:

  • ASCII字元或轉義字元作為單位元組處理。
  • 數制字首(如\X 或 \O)生成對應值得位元組序列
  • Unicode字首會輸出UTF-8碼值的位元組序列

2.8.7 字串與數值之間的轉換

數值轉字串:

  • string(數值, base, pad)函式 base代表數制 pad代表字串對齊

字串轉數值:

  • parse(type, str, base=10) type:結果的資料型別 str :待解析的字串 base :用於說明數制,預設10進位制image-20201012170741865

相關文章