
どうもタスです。
プログラムは、変数に代入する数値や文字列などのリテラルを分類する「型」というものを使用します。
PHPは動的型付け言語のため、変数を使用する際に明示的に型を宣言する必要はないですが、全ての変数は型を持っていて、内部的には明確に分類されています。
そこで今回は、型のうちの一つである「float型」及び「double型」について説明します。
「boolean」型もしくは「integer」型についての説明は以下の記事を参考にしてください。
この記事の目次
PHPの10種類の基本型
PHPは、10種類の基本型をサポートしており、以下のとおりになります。
4種類のスカラー型
- 論理値:boolean
- 整数:integer
- 浮動小数点数:float, double
- 文字列:string
4種類の複合型
- 配列:array
- オブジェクト:object
- callable
- iterable
2種類の特別な型
- リソース:resource
- ヌル:NULL
上記の中で、今回は「浮動小数点数:float, double」に焦点を当てています。
浮動小数点数型「float, double」の説明
実数を表す型を「float」もしくは「double」と言います。
floatのサイズはプラットフォームに依存し、通常はおよそ10進数で14桁(10兆)の精度で、最大値は「1.8e308(1.8×10の308乗)」になります。
なお、以下のとおり、浮動小数点数は複雑な算術演算をする際に誤差が生じるようです。
1 2 |
<?php echo floor((0.1+0.7)*10); // 「7」が出力される |
上記の結果は、内部的な値が「7.9999999999999991118…」になっていることが原因と言われています。
よって、高い精度の算術が必要な場合は、任意精度数学関数(BC Math関数)またはgmp関数を使用しましょう。
float以外の型からfloat型への変換
文字列からfloatへの変換は、文字列中に「.」や「e」、「E」といった文字が含まれず、且つ数値がinteger型の範囲内に収まる場合はintegerに変換されますが、それ以外の場合は全てfloatに変換されます。
また、文字列から数値への変換は、文字列の最初の部分により変換が可能か決まります。
具体的には、文字列の始まりが有効な数値から始まる場合に変換され、そうでない場合は0(ゼロ)と評価されます。
ここでいう有効な数値というのは、符号の後に1つ以上の数字、オプションとして指数部が続く形です。
指数部は「e」または「E」の後に1つ以上の数字が続く形式になります。
1 2 3 4 5 6 7 8 9 10 |
<?php $foo = 1 + "10.5"; // $foo は double です (11.5) $foo = 1 + "-1.0e3"; // $foo は double です (-999) $foo = 1 + "tasu-1.3e3"; // $foo は integer です (1) $foo = 1 + "tasu3"; // $foo は integer です (1) $foo = 1 + "10 tasu"; // $foo は integer です (11) $foo = 1 + "10 tasu"; // $foo は integer です (11) $foo = "10.0 tasu " + 1; // $foo は integer です (11) $foo = "10.0 tasu " + 1.0; // $foo は float です (11) |
ただし、5~6行目は「Warning: A non-numeric value encountered」、7~10行目は「Notice: A non well formed numeric value encountered」が発生します。
数値に変換してからでないとエラーが出力されるみたいですね。
なお、明示的なキャストは「floatval」や「doubleval」、「(float)や(double)」で行います。
1 2 3 4 5 6 7 8 9 10 11 |
<?php $float1 = floatval("1.2345"); $float2 = (float)"6.7891"; $double1 = doubleval("1.2345"); $double2 = (double)"6.7891"; var_dump($float1); // float(1.2345) var_dump($float2); // float(6.7891) var_dump($double1); // float(1.2345) var_dump($double2); // float(6.7891) |
その他の変換は、integer型と同様になります。なお、PHP5以上、オブジェクトを浮動小数点数に変換しようとした場合には、通知が投げられます。
float型の比較演算
浮動小数点数の誤差の個所で説明したとおり、floatは比較するのには問題が生じます。
よって、浮動小数点数値を比較する際は、比較時の丸目誤差の上界を用います。
この値は、計算機イプシロンあるいは丸目単位と呼ばれ、計算時に扱える最小の差分を表します。
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php $a = 1.23456789; $b = 1.23456780; $epsilon = 0.00001; // 「true」と表示される。 if(abs($a-$b) < $epsilon) { echo "true"; } else { echo "false"; } |
NaNの取り扱い方
「NaN」とは「Not a Number」の略で、浮動小数点演算において未定義の値、あるいは表現不能な値を表すfloat型の値を言います。
一応、数値の仲間ではありますが、非数ということで数学関数などで無効な値となった場合に発生します。
この値を他の値と比較すると、結果はFALSEになりますので、チェックする際にはNaNを判定するis_nan()関数を使用しましょう。
1 2 3 4 5 |
<?php echo acos(1.01); // NAN echo '<br>'; var_dump(is_nan(acos(1.01))); // bool(true) |