perlnumber - Perl
中數字的語義以及算術操作
$n = 1234; # 十進位制數
$n = 0b1110011; # 二進位制數
$n = 01234; # 八進位制數
$n = 0x1234; # 十六進位制數
$n = 12.34e-56; # 指數形式
$n = "-12.34e56"; # 用字串描述的數
$n = "1234"; # 用字串描述的數
這篇文章描述了Perl內部是怎樣處理數的數值的。
在這裡不會提到Perl的運算子過載機制,運算子過載允許使用者自定義對數的操作,例如對任意大的整型數或者任意精度的浮點數進行的操作,或者一些其它的算術型別如求模操作和p-adic操作等等。要想知道運算子過載的細節,請看過載。
Per在內部能用三種方法表示數值:用“Native整型”,“Native浮點型”或是用十進位制形式的字串。其中十進位制字串可以帶一個指數描述的部分,就像"12.34e-56"。在這裡術語
Native的含義是用於編譯
perl 的 C
編譯器所支援的型別。
在我們談及整型時,"native"這個術語所包含的含義比我們談論浮點數時要少一些。對"native"整型來說,這個術語所的含義僅僅是指整型數的可以有最大值和最小值會是2的某次方,而對"native"浮點數來說,有一條基本的限制就是它只能表示那些能用有限幾位二進位制小數所表示的實數。舉例來說,0.9就不是"native"浮點數,因為0.9用二進位制小數表示是有無窮多位的:
二進位制0.1110011001100...
序列 1100
將無休止的迴圈下去。除了這條限制以外,二進位制浮點數在用指數型式表達時也存有限制。在特定的硬體條件下,浮點型的數可以儲存最多53位二進位制數再加上範圍從-1024到1024的指數值(譯者:-1024到1024用11位二進位制數,加上53等於64,就是說這裡用用64位存一個浮點數)轉換成十進位制也就是說差不多能用16位有效數字和從-304到304的指數值和起來表示一個浮點數。這種表示方法的一種結果就是我們不可能在不損失精度的情況下用浮點型儲存像12345678901234567這樣的數。
類似的,十進位制字串也只能表示有限位數的十進位制數.光就字串來言,它可以是任意長度的,沒有什麼關於指數或有效數字位數上的限制.(但是請意識到我們正在討論的存放數值的那些規則.事實是你能用字串存放很大的數值並不代表相應的數值操作能夠把字串中的所有的數位都用上.欲知詳情,請看"數值運算子和數值轉換"
事實上“Native整型數”儲存的數值可以是帶符號的,或者是不帶符號的。所以很典型的,Perl中“Native整型數”可以表示的整數的範圍是-2**31..2**32-1,這個範圍對64位的整數來說是比較合適的。但這並不意味著Perl只能處理這個範圍內的整數:浮點型別可以存下更大的整數。
總而言之,Perl中的數是有限位數的十進位制數或者說是足夠短的二進位制數。
就像前面說的那樣,Perl可以用三種格式中的任意一種存放一個數,但是大多數運算子只能理解這三種格式中的一種。當一個數值作為引數傳給一個運算子時,它將會被轉換成運算子可以理解的那種格式。
可能出現的轉換有下面六種:
native 整型 --> native 浮點型 (*)
native 整型 --> 十進位制形式的字串
native 浮點型 --> native 整型 (*)
native 浮點型 --> decimal string (*)
十進位制的字串 --> native 整型
十進位制的字串 --> native 浮點型 (*)
這些轉換按照下列的規則進行:
- •
- 如果原來的數可以用要轉換成的格式表述,則其值繼續使用,不會改變。
- •
- 如果原來的數超出了要轉換成的格式所能表述的極限,則最接近極限的那個值會被用來做最後的值。(這會有資訊上的損失)
- •
- 如果原來的數在要轉換成的格式所能表述的兩個相鄰的數之間,則這兩個數中的一個會被用來做最後的值。(這會有資訊上的損失)
- •
- 在 "native 浮點型 -->
native 整型"
的轉換中,結果的值小於等於原來的值。(因為是直接擷取小數位取整的)(
"Rounding to zero".)
- •
- 如果
"十進位制的字串 -->
native 整型"
的轉換不能在不損失資訊的情況下完成,結果將會和下列的轉換序列的結果一致:"十進位制的字串
--> native_浮點型 -->
native_整型".
特別要指出的是,儘管像
"0.99999999999999999999"
這樣的數可能會取整成1,取整一般是傾向於0的。
限制: 上面標有 "(*)"
的轉換包含有C編譯器的動作步驟。在特殊情況下,C編譯器的一些特性或者Bugs可能會導致上述一些規則的不成立。
Perl
中帶有數值引數的操作將按照四種方法處理引數:它們可能會將引數強制轉換為整型,浮點型或是字串型中的一種,或者按照運算元的格式來處理引數。在把一個數的型別強制轉換成另一種特定的型別的過程中,原來儲存的值不會改變。
所有需要整型數作引數的運算子會對引數進行取模的操作。比如說用32位存放整型數時會把數對2的32次方取模
("mod 2**32"),所以 "sprintf "%u",
-1" 的結果和 "sprintf "%u",
~0" 的結果是一樣的。
- Arithmetic operators
算術運算子
- 二進位制運算子
"+" "-" "*" "/" "%"
"==" "!=" ">" "<"
">=" "<="
以及一元運算子 "-"
"abs" and "--"
總試圖將引數轉換為整形。如果轉換都可以無損精度地進行,並且運算也無損於精度,那麼返回整數的結果。否則,引數被轉換為浮點數,返回浮點數結果。轉換的緩衝過程保證了整數轉換不會將浮點數的零頭丟掉
- ++
- "++"
的行為與其他運算子類似,但是如果運算元是滿足
"/^[a-zA-Z]*[0-9]*\z/"
格式的字串,將進行
perlop
中描述的字串遞增運算。
- 定義了 "use integer"
時的算術運算
- 在 "use integer;"
的作用範圍內,幾乎上面列出的所有運算子都將它們的運算元轉換為整數,返回整數的結果,例外情況是
"abs", "++" 和
"--",在這種情況下不改變行為。
- Other mathematical operators
其他數學運算子
- 類似 "**", "sin" 和
"exp"
的運算子強制引數為浮點格式。
- Bitwise operators 位運算子
- 如果不是字串,運算元被強制轉換為整型
- 定義了 "use integer"
時的位運算
- 強制引數為整型。並且,移位操作在內部使用有符號整型而不是預設的無符號數
- 需要整型運算元的運算子
- 強制運算元轉換為整型。例如,在函式
"sysread"
的第三和第四個引數中,這樣做是合適的。
- 需要字串的運算子
- 強制運算元為字串格式。例如,在
"printf "%s", $value"
中,這樣做是合適的。
儘管強制轉換引數為特定格式不會改變已儲存的數字,Perl
會記錄轉換的結果。特別的,儘管第一次轉換會耗費一定時間,重複進行的操作不會需要重新轉換。
Ilya Zakharevich "
[email protected]"
由 Gurusamy Sarathy <
[email protected]> 編輯
由 Nicholas Clark <
[email protected]> 更新為 5.8.0
版
overload, perlop
本頁面中文版由中文 man
手冊頁計劃提供。
中文 man 手冊頁計劃:
https://github.com/man-pages-zh/manpages-zh