[Perl] 程式設計教學:資料型別 (Data Type)

【分享本文】
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

    前言

    在電腦程式中,資料型別用來界定資料合法的操作,像是數字間可進行四則運算,字串可相接等。Perl 的純量 (scalar) 有以下數種資料型別:

    • 數字 (number)
    • 字串 (string)
    • 參考 (reference)
    • 其他型別

    純量本身沒有綁定特定型別,寫 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 獨有的問題,而是大部分程式語言會碰到的議題。只有少數像 Perl 6 等語言可以進行精準的小數點運算,但實務上幾乎不會有程式人用 Perl 6 進行數值運算,不能過度依賴 Perl 6 等少數語言所提供的特性。

    字串 (String)

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

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

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

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

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

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

    特殊字串括號

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

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

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

    my $name = "Michael";
    
    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 程式不會用到參考。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email
    【追蹤新文章】
    Facebook Twitter Plurk