介紹 PHP 中的資料型態 (型別),包含布林 (Boolean)、整數 (Integer)、浮點數 (Float),型別的判斷與轉型。

簡介

型別的種類

PHP 有 8 種基本的資料型態 (Data Type) 或簡稱型別 (Type):
4種數值 (scalar) 的型別:

  • 布林 (boolean)
  • 整數 (integer)
  • 浮點數 (float 或 double)
  • 字串 (string)

2種複合 (compound) 的型別:

  • 陣列 (array)
  • 物件 (object)

另外兩種特別的型別:

  • 資源 (resource)
  • 空值 (NULL)

為了方便閱讀另外也有幾種虛擬的型別:

  • 混合 (mixed)
  • 數字 (number)
  • 回呼 (callback)

型別的判斷

可利用 get_type() 函式取得型別種類或利用 is_xxx() 函式判斷變數是否為此型別( is_xxx()xxx 替換為要判斷的型別,例如:is_integer)。比較特別的是 is_numeric() 函式,當傳入的參數為整數、浮點數或是純數字內容的字串,都回傳 TRUE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$a_bool = TRUE;                       // boolean
$an_int = 12; // integer
$a_float = 1.23; // float
$a_string = "foo"; // string
$a_array = array(); // array
$a_object = new stdClass; // object
$a_resource = fopen("res.txt","w+"); // resource
$a_null = NULL; // NULL

echo gettype($a_bool); // 印出: boolean
echo gettype($an_int); // 印出: integer
echo gettype($a_float); // 印出: double
echo gettype($a_string); // 印出: string
echo gettype($a_array); // 印出: array
echo gettype($a_object); // 印出: object
echo gettype($a_resource); // 印出: resource
echo gettype($a_null); // 印出: NULL

if (is_bool($a_bool)) echo "會顯示";
if (is_integer($an_int)) echo "會顯示";
if (is_float($a_float)) echo "is_float 可以";
if (is_double($a_float)) echo "is_double 也可以";
if (is_string($a_bool)) echo "不會顯示";
if (is_array($a_array)) echo "會顯示";
if (is_object($a_object)) echo "會顯示";
if (is_resource($a_resource)) echo "會顯示";
if (is_null($a_null)) echo "會顯示";

$a_string = "169.99cm";
$a_string2 = "178";

if (is_numeric($a_bool)) echo "不會顯示";
if (is_numeric($an_int)) echo "會顯示";
if (is_numeric($a_float)) echo "會顯示";
if (is_numeric($a_string)) echo "不會顯示";
if (is_numeric($a_string2)) echo "會顯示";

fclose($a_resource);

另外可以利用 var_dump() 函式列出變數完整的內容與型別以便 debug

布林 (Boolean)

語法

布林的值只有兩種,TRUEFALSE,不分大小寫。

1
2
$flag = FaLsE;
var_dump($flag == fAlSe); // bool(true)

轉型

要轉型為布林可利用以下方式

  • 利用 (bool)(boolean) 的強制轉型 (Cast)。
  • 利用 settype() 傳入引數 "bool""boolean" 轉型。("bool" 為 PHP 4.2.0 之後新增)

要注意的是,settype() 必須傳入變數,而執行之後將會直接修改變數的內容。

1
2
3
4
5
$num = 10;
var_dump((bool) $num); // bool(true)
var_dump($num); // int(10), $num 不會被修改
settype($num, "boolean");
var_dump($num); // bool(true), $num 被修改

以下情況轉型為布林時,結果為 FALSE

  • boolean 型別值為 FALSE 之變數
  • integer 型別值為 0 之變數
  • float 型別值為 0.0 之變數
  • string 為空字串或值為 "0" 之變數
  • 空陣列 array 之變數
  • NULL
  • 無成員之 object 型別之變數(PHP 4 之前,PHP 4 之後 object 轉型永遠為 TRUE)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var_dump((bool) 0);             // bool(false)
var_dump((bool) -1); // bool(true), 注意這裡可能會搞錯
var_dump((bool) 0.0); // bool(false)
var_dump((bool) 169.99); // bool(true)
var_dump((bool) ""); // bool(false)
var_dump((bool) "0"); // bool(false)
var_dump((bool) "false"); // bool(true), 注意這裡可能會搞錯
var_dump((bool) array()); // bool(false)
var_dump((bool) array(false)); // bool(true)
var_dump((bool) new stdClass); // bool(true), PHP 4 之前: bool(false)

$fp = fopen("res.txt","w+");
var_dump((bool) $fp); // bool(true)
fclose($fp);

var_dump((bool) NULL); // bool(false)

整數(Integer)

語法

整數型別顧名思義就是只能存整數,以數學表示的話為 Z = {…, -2, -1, 0, 1, 2, …},整數有三種宣告方式:

  • 十進位制。
  • 十六進位制,以 0x 開頭。
  • 八進位制,以 0 開頭。
1
2
3
$num = 123;   // 十進位寫法
$num = +0x7B; // 十六進位寫法 (等於十進位 123),以 0x 開頭
$num = -0173; // 八進位寫法 (等於十進位 -123),以 0 開頭

以正規表示法表示的話為

1
2
3
4
5
6
7
8
9
10
decimal     : [1-9][0-9]*
| 0

hexadecimal : 0[xX][0-9a-fA-F]+

octal : 0[0-7]+

integer : [+-]?decimal
| [+-]?hexadecimal
| [+-]?octal

八進位中出現無效的數字8或9時,會忽略該數字之後的部份。

1
$num = 01891234; // 結果為 01

數值範圍與溢位

整數的數值範圍會與使用平台有關,例如 32 位元的平台整數使用 4 byte 存放,可使用 PHP 常數 PHP_INT_SIZE 取得該平台的 int 佔用的大小,另外可用 PHP_INT_MAX 取得整數的最大值。

當變數的數值超過平台 int 容許範圍時也就是所謂的溢位 (Overflow),將會自動轉為 float 型別,另外進行除法而除不盡時也會轉型為 float。

1
2
3
4
5
6
$num = PHP_INT_MAX;
var_dump($num); // int(2147483647)
$num++;
var_dump($num); // float(2147483648)
var_dump(28/7); // int(4)
var_dump(25/7); // float(3.5714285714286)

轉型

要轉型為整數可利用以下方式

  • 利用 (int)(integer) 的強制轉型。
  • 利用 intval() 函式轉型。
  • 利用 settype() 傳入引數 "int""integer" 轉型。("int" 為 PHP 4.2.0 之後新增)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var_dump((int) false);         // int(0)
var_dump((int) true); // int(1)
var_dump((int) 169.99); // int(169)
var_dump((int) "9527"); // int(9527)
var_dump((int) ""); // int(0)
var_dump((int) "one"); // int(0)
var_dump((int) "30cm"); // int(30)
var_dump((int) array()); // int(0)
var_dump((int) array(55, 66)); // int(1)
var_dump((int) new stdClass); // int(1)

$fp = fopen("res.txt","w+");
var_dump((int) $fp); // int(3), 3 為 resource 的編號
fclose($fp);

var_dump((int) NULL); // int(0)

字串轉型為整數 (或之後的浮點數) 時,類似八進位數字,會忽略出現無效的字元之後的部份。

轉型為整數時,若有小數點則無條件捨去,但是注意,若該數字超出整數範圍時,會出現不如預期的結果,如果你是想做『取整數』的動作的話,可以使用 floor() 函式來處理。另外,若要四捨五入的話可使用 round() 函式。

1
2
3
4
$num = 201012312359.99;
var_dump((int) $num); // int(-851150553)
var_dump(floor($num)); // float(201012312359)
var_dump(round($num)); // float(201012312360)

浮點數(Float)

語法

浮點數英文 Floating point number 簡稱 float 或 double ,有兩種寫法:

  • 一般數字。
  • 科學記號表示法,使用 e 表示 10 的幾次方,e 不分大小寫。
1
2
3
var_dump(169.99);  // float(169.99)
var_dump(9.527e3); // float(9527)
var_dump(1E-3); // float(0.001)

以正規表示法表示的話為

1
2
3
LNUM          [0-9]+
DNUM ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM [+-]?(({LNUM} | {DNUM}) [eE][+-]? {LNUM})

轉型

要轉型為浮點數可利用以下方式

  • 利用 (float)(double) 的強制轉型。
  • 利用 floatval()doubleval() 函式轉型。(floatval() 為 PHP 4.2.0 之後新增)
  • 利用 settype() 傳入引數 "float""double" 轉型。("float" 為 PHP 4.2.0 之後新增)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var_dump((float) false);         // float(0)
var_dump((float) true); // float(1)
var_dump((float) 178); // float(178)
var_dump((float) ""); // float(0)
var_dump((float) "169.99cm"); // float(169.99)
var_dump((float) array()); // float(0)
var_dump((float) array(55, 66)); // float(1)
var_dump((float) new stdClass); // float(1)

$fp = fopen("res.txt","w+");
var_dump((float) $fp); // float(3), 3 為 resource 的編號
fclose($fp);

var_dump((float) NULL); // float(0)

常見問題

取小數點位數

如果我們想要只顯示到小數點第二位,可以用幾種方式處理:

  • 使用 round() 函式,前面也曾使用過,只要再進一步指定第二個參數,就可以拿來取小數點位數。
  • 使用 number_format() 函式,第二個參數表示到小數點第幾位。
  • 使用 sprintf() 函數,%f 表示輸出浮點數,%.2f 表示小數點第二位。
1
2
3
4
5
6
7
8
9
10
11
12
13
$num = 98.765;
// 參數二的對照範例
// ... 0 9 8 . 7 6 5 ...
// ... -2 -1 0 1 2 3 ...
var_dump(round($num, 2)); // float(98.77) 取小數點第二位
var_dump(round($num, -2)); // float(100) 取到百位
var_dump(number_format($num, 2)); // string(5) "98.77"
var_dump(sprintf("%.2f", $num)); // string(5) "98.77"
// 亦可用來保留0的顯示
$num = 10.00;
echo $num; // 10
$num = sprintf("%.2f", $num);
echo $num; // 10.00 保留00

近似值

在電腦世界中的浮點數其實只是近似值,浮點數中的整數可能只是精確度到達一定程度而已,所以可能會在某些情況下造成判斷錯誤,下面有些例子與一個變通的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$num = 169.99999999999;
var_dump($num); // float(169.99999999999)
$num = 169.999999999999;
var_dump($num); // float(170)
$num = 8.0;
$num2 = (0.1+0.7) * 10;
var_dump((int) $num2); // int(7) !!
var_dump($num == $num2); // bool(false) !!
var_dump(floatEqual($num, $num2)); // bool(true)

// 誤差值小於 $precision 視為相等
function floatEqual($num, $num2, $precision=0.0001) {
return (abs($num - $num2) < $precision);
}

取餘數

當變數為超過整數型別容許範圍的浮點數時,進行取餘數 (modulo) 動作可能會得到錯誤的結果,以下為範例與一個解決方案:

1
2
3
4
5
6
7
8
$num = 6887129853;
var_dump($num % 10); // % 10 取表示除以 10 之後的除數, 結果錯誤: int(-9)
var_dump(floatMod($num, 10)); // float(3)

// 餘數 = 被除數 - 商數 * 除數
function floatMod($num, $divisor) {
return $num - floor($num / $divisor) * $divisor;
}

延伸閱讀

上一篇 PHP教學 - 基本語法 (Syntax)
下一篇 PHP 教學 - 資料型態 (Data Type) - 下