開源技術教學網 [Perl] 程式設計教學:資料型態 (Data Type)

最後修改日期為 JAN 30, 2022

前言

在電腦程式中,資料型態用來界定資料所占的記憶體大小及該資料合法的操作,像是數字間可進行四則運算,字串可相接等。Perl 有以下數種資料型態:

  • 純量 (scalar)
    • 數字 (number)
    • 字串 (string)
    • 參考 (reference)
  • 陣列 (array)
  • 雜湊 (hash)

純量是單獨的值,後兩者則是容器。純量本身沒有綁定特定型態。寫 Perl 程式時也不需要宣告純量的型態,Perl 會自動判定純量當下的型態,並視需求自動轉換。

數字 (Number)

Perl 的數字可能是整數 (integer) 或浮點數 (floating-point numbers),支援以下表示法:

my $x = 12345;         # integer
my $x = 123.45;        # floating point
my $x = 6.02e23;       # scientific notation
my $x = 1000_000_000;  # long int with better readability
my $x = 0377;          # octal
my $x = 0xff;          # hexadecimal (hex)
my $x = 0b1100_0000;   # binary

前四個數字為一般常見的十進位數。但 Perl 支援其他進位系統:

  • 0 開頭表示八進位數
  • 0x 開頭表示十六進位數
  • 0b 開頭表示二進位數

要將字串轉為相對應的數字時,可用以下函式:

  • int:去除小數點部分,僅回傳整數
  • oct:轉成二進位、八進位、十六進位數
  • 浮點數可自動轉換

浮點數的誤差

由於浮點數內部儲存的方式,進行浮點數運算時有可能會引入微小的誤差。見下例:

my $n = 0;

while ($n != 1) {
    # Do something here.

    $n += 0.1;
}

在理想的狀態下,$n 每跑一輪迴圈會遞增 0.1,跑十輪後就可以終止此 while 迴圈。但是,每次進行小數運算時會引進微小的誤差,實際上 $n 會跳過 1 後繼續遞增,造成非預期的無窮迴圈。

解決浮點數誤差的想法如下:

|實際值 - 誤差值| < 誤差

要注意誤差無法消除,只能藉由運算儘可能地縮小誤差到合理的範圍內。

我們將前例改寫如下:

my $n = 0;

while (abs($n - 1) > 1 / 100000) {
    # Do something here.

    $n += 0.1;
}

隨著 $n 遞增,誤差會逐漸縮小,最後在滿足條件時迴圈會結束。

這並不是 Perl 獨有的問題,而是大部分程式語言會碰到的議題。只有少數像 Raku 等語言可以進行精準的小數點運算,但實務上幾乎不會有程式人用 Raku 進行數值運算,不能過度依賴 Raku 等少數語言所提供的特性。

字串 (String)

字串實字可用一對 '' 單引號或是一對 "" 雙引號包起來,兩者的差別在於前者不會進行字串安插 (string interpolation) 而後者會。以下是實例:

my $name = "Michelle";

'Hello $name' == "Hello \$name" or die "Wrong value";
"Hello $name" == "Hello Michelle" or die "Wrong value";

在使用單引號包住 Hello $name 時,$name 不會插入實際的值,而會保持字面上的字元;相對來說,使用雙引號包住同一字串時,$name 會代換成 "Michelle",所以會得到不同的結果。

\ (slash) 在雙引號字串的意思是跳脫下一個字元原本的意思,像是 \$ 代表不要解析 $ 而把其視為普通字串。有些字母會有特殊意義,如下:

  • \n:換行
  • \t:插入 TAB
  • \\:將下一個 \ 視為普通字串
  • \$:將下一個 $ 視為普通字串

這裡有更多的跳脫字元,讀者可自行參考。

特殊字串括號

除了原本的單/雙引號之外,Perl 還支援另一套寫法:

  • q//:相當於單引號字串
  • qq//:相當於雙引號字串
  • qx//:將字串視為命令列程式來執行
  • qw//:字串串列
  • qr//:正規表示式

為什麼要引入這套寫法呢?這是為了避免過多的 \ (slash),如下例:

my $name = "Michelle";

qq("Perl is awesome!", $name said.) eq "\"Perl is awesome!\", $name said." 
    or die "Wrong value";

使用正規的雙引號字串時,我們要跳脫內部的雙引號,以免字串提早結果,但用 qq() 代替雙引號時,則不需跳脫內部的雙引號,可簡化程式碼。

自動型態轉換

Perl 會根據程式所在的情境境自動將資料轉換型態。如下例:

"2" * 3 == 6 or die "Wrong value\n";

Perl 程式會自動將字串 "2" 轉為數字 2 後進行運算。這樣的程式碼不是好的寫法,只是用來展示 Perl 的特性。

參考 (Reference)

參考是相對進階的概念,主要用於製作複合資料結構 (complex data structures),像是多維陣列或是混合陣列及雜湊的結構等,初階的 Perl 程式不會用到參考。

陣列 (Array)

陣列是線性、有序的容器。我們會在後文介紹陣列。

雜湊 (Hash)

雜湊是以鍵值對為儲存單位的非線性容器。我們會在後文介紹雜湊。

分享本文
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Yahoo
追蹤本站
Facebook Facebook Twitter