NAME¶
perlnumber - Perl
中數字的語義以及算術操作
SYNOPSIS 總覽¶
$n = 1234; # 十進制數
$n = 0b1110011; # 二進制數
$n = 01234; # 八進制數
$n = 0x1234; # 十六進制數
$n = 12.34e-56; # 指數形式
$n = "-12.34e56"; # 用字符串描述的數
$n = "1234"; # 用字符串描述的數
DESCRIPTION 描述¶
這篇文章描述了Perl內部是怎樣處理數的數值的。
在這裏不會提到Perl的運算符重載機制,運算符重載允許使用者自定義對數的操作,例如對任意大的整型數或者任意精度的浮點數進行的操作,或者一些其它的算術類型如求模操作和p-adic操作等等。要想知道運算符重載的細節,請看重載。
Storing numbers 數值存儲¶
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中的數是有限位數的十進制數或者說是足夠短的二進制數。
Numeric operators and numeric conversions 數值運算符和數值轉換¶
就像前面說的那樣,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可能會導致上述一些規則的不成立。
Flavors of Perl numeric operations 數值操作的特色¶
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
會記錄轉換的結果。特別的,儘管第一次轉換會耗費一定時間,重復進行的操作不會需要重新轉換。
AUTHOR 作者¶
Ilya Zakharevich "ilya@math.ohio-state.edu"
由 Gurusamy Sarathy <gsar@ActiveState.com> 編輯
由 Nicholas Clark <nick@ccl4.org> 更新為 5.8.0
版
SEE ALSO 參見¶
overload, perlop