perlnumber - Perl での数値と数値操作の意味論
$n = 1234; # 10 進数
$n = 0b1110011; # 2 進数
$n = 01234; # 8 進数
$n = 0x1234; # 16 進数
$n = 12.34e-56; # 指数表現
$n = "-12.34e56"; # 文字として指定された数値
$n = "1234"; # 文字として指定された数値
この文書は、Perl が内部で数値をどのように扱うかを記述します。
Perl の演算子オーバーロード機能はここでは完全に無視されます。 演算子オーバーロードは、任意の大きさの整数、任意の精度の浮動小数点数、 合同算術や p 進数算術などの「特殊な」数値の演算などの数値に関するユーザー定義の 振る舞いを指定できます。 詳細については overload を参照してください。
Perl は内部的に数値を 3 つの異なった方法で表現できます: ネイティブな整数、 ネイティブな浮動小数点数、10 進文字列です。 10 進文字列は "12.34e-56"
のように指数部がある場合もあります。 ここでの ネイティブな というのは、「perl をビルドする際に使われた C コンパイラが対応している形式」を意味します。
「ネイティブの」という用語はネイティブな整数に関して話すときにはほとんど 意味はなく、ネイティブな浮動小数点数に関わる際に意味があります。 整数に対して「ネイティブな」という用語が暗示する唯一のものは、 対応している真の整数量の最大値と最小値は 2 のべき乗に近いということです。 しかし、「ネイティブな」浮動小数点数は最も基本的な制限を持ちます: 2 進数分数に変換したときに相対的に「短い」表現を持つ値のみを表現できます。 例えば、0.9 はネイティブな浮動小数点では表現できません; なぜなら 0.9 の 2 進数の分数は無限となるからです:
binary0.1110011001100...
1100
が繰り返されます。 この制限にくわえて、2 進数の指数も、浮動小数点数として表現されると 制限されます。 典型的なハードウェアでは、浮動小数点数は 53 桁までの 2 進数と、 -1024 から 1024 までの 2 進数指数を保管できます。 10 進表現では、ほぼ 16 桁の 10 進数と -304 から 304 の範囲の指数となります。 これら全ての結論は、このようなアーキテクチャでは、Perl は 12345678901234567 といった数を情報の欠落なしに浮動小数点数として 保管することはできないということです。
同様に、10 進文字列は有限 10 進記数法を持つ数値のみ表現できます。 文字列であるため、従って任意の長さを持つため、これらの数値のための 指数部や実数部には実用上の制限はありません。 (しかし、議論しているのはこれらの数値の 保管 に関するものであると いうことを理解してください。 このような「大きい」数値を保管できるということは、これらの数値による 操作 が全ての桁を使うということを意味しません。 詳細については "Numeric operators and numeric conversions" を 参照してください。)
実際のところ、ネイティブな整数形式で保管された数値は、符号付きのネイティブな 形式か、符号なしのネイティブな形式のどちらかで保管されます。 従って、ネイティブな整数として保管される Perl の数値の限界は、典型的には -2**31..2**32-1 で、64 ビット整数の場合は適切に修正されたものになります。 再び、これは Perl がこの幅でのみ整数を扱えるということを意味しません: 浮動小数点形式によってもっと多くの整数を保管可能です。
要約すると、Perl の数値は、有限 10 進数記法か、「短い」2 進数記法を持つ 数値のみが格納できます。
前述のように、Perl は 3 つの形式のどれでも数値を格納できますが、 ほとんどの演算子は典型的にはこれらの形式の一つだけしか理解しません。 数値がそのような演算子の引数として渡されるとき、演算子が理解できる形式へ 変換されます。
6 種類のこのような変換が可能です:
ネイティブな整数 --> ネイティブな浮動小数点数 (*)
ネイティブな整数 --> 10 進数文字列
ネイティブな浮動小数点数 --> ネイティブな整数 (*)
ネイティブな浮動小数点数 --> 10 進数文字列 (*)
10 進数文字列 --> ネイティブな整数
10 進数文字列 --> ネイティブな浮動小数点数 (*)
これらの変換は、以下の一般的な規則に従います:
変換元の数値が変換先の形式で表現できるなら、その表現が使われます。
変換元の数値が変換先の形式で表現できる限界を超えている場合、最も近い 限界値が用いられます。 (情報の欠落)
変換元の数値が変換先の形式で表現できる二つの数値の間にある場合、 二つの数値表現のどちらかが使われます。 (情報の欠落)
<ネイティブな浮動小数点数 --
ネイティブな整数>> 変換で、結果の絶対値は 変換元の絶対値以下となります。 (「0 への丸め」。)
もし <10 進数文字列 --
ネイティブな整数>> 変換が情報の欠落なしに 行えない場合、結果は <10 進数文字列 --
ネイティブな浮動小数点数 --> ネイティブな整数>> という 変換に準拠します。 特に、丸めは 0 方向に強く偏っていますが、 "0.99999999999999999999"
のような数が 1 に丸められる可能性はあります。
制限: 上記で (*)
マークが付いている変換は C コンパイラによって 行われます。 特に、使用しているコンパイラのバグ/仕様が上記のルールの一部を破ることに なるかもしれません。
数値の引数を取る Perl の操作は、引数を 4 つの異なる方法のどれかによって 扱われます: 整数/浮動小数点数/文字列数のどれかに強制されるか、 オペランドの形式に依存して異なる振る舞いをするかです。 特定の形式への数値の強制は、保管されている値は変更しません。
引数として整数形式を必要とする全ての演算子は引数を合同算術として扱います; つまり、32 ビットアーキテクチャでは mod 2**32
です。 従って、sprintf "%u", -1
は sprintf "%u", ~0
と同じ結果となります。
2 項演算子 +
-
*
/
%
==
!=
>
<
>=
<=
と、単項演算子 -
abs
--
は引数を整数に 変換しようとします。 もし両方の変換は精度を失うことなく可能で、演算が精度を失うことなく 実行できるなら、整数の結果が使われます。 さもなければ、引数は浮動小数点数形式に変換され、浮動小数点数の結果が 使われます。 (上述したような)変換のキャッシュは、整数変換が浮動小数点数の小数部を 捨てないことを意味します。
++
は上述のその他の演算子と同様に振る舞いますが、もし文字列が /^[a-zA-Z]*[0-9]*\z/
にマッチングする形式なら、perlop に記述している 文字列インクリメントが使われます。
use integer
中の算術演算子use integer;
が有効なスコープ中では、上述のほとんど全ての演算子は 引数を整数形式に強制し、整数の結果を返します。 例外は abs
, ++
, --
で、use integer;
でも振る舞いは変わりません。
**
, sin
, exp
といった演算子は引数を浮動小数点数に強制します。
引数は、文字列でなければ整数に強制されます。
use integer
中のビット単位演算子引数を整数に強制します。 また、シフト操作は、デフォルトの符号なし整数ではなく、符号付き整数を 内部的に使います。
引数を整数に強制します。 これは例えば、sysread
の第 3 引数と第 4 引数に適用されます。
引数を文字列に強制します。 例えば、これは printf "%s", $value
に適用されます。
引数の特定の形式への強制は保管されている数値は変更しませんが、Perl は変換の 結果を覚えています。 特に、最初の変換が時間がかかるものであったとしても、同じ操作を繰り返しても 変換を再実行する必要はありません。
Ilya Zakharevich ilya@math.ohio-state.edu
Editorial adjustments by Gurusamy Sarathy <gsar@ActiveState.com>
Updates for 5.8.0 by Nicholas Clark <nick@ccl4.org>