数据类型之四种标量类型

在关于变量的章节中,我们已经知道 PHP 支持 9 种原始数据类型,在这里我们再次复习一下:

四种标量类型

  • Boolean:布尔值。仅有两个值,TRUEFALSE
  • Integer:整数型
  • Float:浮点数,也称作double,表示带小数点的小数,例如66.66
  • String:字符串

三种复合类型

  • Array:数组
  • Object:对象
  • Callable:可调用类型

两种特殊类型

  • Resource:资源类型,保存了到外部资源的一个引用
  • NULL:表示一个变量没有值,只有唯一的可能值NULL

复习完毕,我们首先来了解四种标量类型

Boolean:布尔值

布尔值仅有两个可能的值:TRUEFALSE(不区分大小写),代表逻辑上的真与假,常用于条件语句中的判断。

1. 赋值

本教程将始终使用var_dump()函数来判断变量的数据类型及值。

布尔类型赋值只需将truefalse指定给变量即可,例如:$boolean = TRUE;

示例代码如下:

<?php

$boolean = true;// 指定布尔值
var_dump($boolean);// 输出:bool(true)

2. 转换为布尔值

在运算符、函数或者流程控制结构需要一个boolean参数时,该参数会自动转化为布尔值以供判断。在其他需要明确其布尔值的情况下,可以使用强制类型转化。 示例代码如下:

<?php

$str = '一个可怜的即将被强制转换为布尔值的字符串';
$str = (bool)$str;// 强制类型转换:在需要被转换的变量之前加上使用小括号包裹要转换的数据类型
var_dump($str);// 输出:bool(true)

$str = '字符串在逻辑判断上属于true';
var_dump((bool)$str);// 输出:bool(true)

$str = '';// 空字符串在逻辑判断中属于 false
var_dump((bool)$str);// 输出:bool(false)

$num = 4366;// 非零数字在逻辑判断中属于 true
var_dump((bool)$num);// 输出:bool(true)

$num = 0;// 数字 0 在逻辑判断中属于 false
var_dump((bool)$num);// 输出:bool(false)

$str = '0';// 为'0'的非空字符串在逻辑判断中属于 false
var_dump((bool)$str);// 输出:bool(false)

$float = 0.0;// 数值为0.0的浮点数在逻辑判断中属于 false
var_dump((bool)$float);// 输出:bool(false)

$null = null;// NULL类型变量在逻辑判断中属于 false
var_dump((bool)$null);// 输出:bool(false)

$arr = [];// 空数组在逻辑判断中属于 false
var_dump((bool)$arr);// 输出:bool(false)

$arr = [1, 2, 3, 'jisu', 'PHP教程'];// 非空数组在逻辑判断中属于 true
var_dump((bool)$arr);// 输出:bool(true)

$nan = NAN;
var_dump((bool)$nan);// 输出:bool(true)

上述代码也说明了当某些值被强制转换为 Boolean 类型时被认为是TRUE还是FALSE

总的来说,当以下值被转换为 Boolean 类型时,会被认为是 FALSE ,其余都是 TRUE :

  • 布尔值本身
  • 空字符串,以及字符串'0'"0"
  • 整型值0,和浮点型值0.0
  • 空数组
  • 特殊类型NULL,以及尚未赋值的变量
  • 从空标记生成的 SimpleXML 对象

Integer:整型

整型是指没有小数点的数字,在 PHP 中,不支持无符号的 Integer(即所有整型都是带符号的,正整数和0可忽略符号+)。可以看下面的代码:

<?php

echo +0;// 输出:0
echo PHP_EOL;

echo -0;// 输出:0
echo PHP_EOL;

var_dump(-0);// 输出:int(0)
var_dump(-7);// 输出:int(-7)
var_dump(+9);// 输出:int(9)

整型值可以使用二进制(数字前必须加上0b)、八进制(数字前必须加上0)、十进制和十六进制(数字前必须加上0x)。示例代码如下:

<?php

$binary = 0b11111;// 二进制数
var_dump($binary);// 输出:int(31)

$hexadecimal = 0x1A;// 十六进制数
var_dump($hexadecimal);// 输出:int(26)

$octal = 01234;// 八进制数
var_dump($octal);// 输出:int(668)

$decimal = 6789;// 十进制数
var_dump($decimal);// 输出:int(6789)

当给定的整型值超出了 Integer 的范围,将会被解释为float类型。示例代码如下:

<?php

## 始终建议使用最新版的PHP

// 自 PHP 4.4.0 和 PHP 5.0.5后,最大值可以用常量 PHP_INT_MAX 来表示,最小值可以在 PHP 7.0.0 及以后的版本中用常量 PHP_INT_MIN 表示。
echo PHP_INT_MAX;// 输出:9223372036854775807
echo PHP_EOL;

$int = PHP_INT_MAX;
var_dump($int);// 输出:int(9223372036854775807)

// 超出整型数的字长和,将被解释为 浮点数
$int = PHP_INT_MAX + 1;
var_dump($int);// 输出:float(9.2233720368548E+18)

转换为整型

当运算符,函数或流程控制需要一个Integer参数时,值会自动转换。还可以通过函数intval()来将一个值转换成整型。而需要明确将一个值转化为整型时,也可使用强制类型转换。

下方代码列出了一些其他类型转换为整型时的结果:

<?php

$str = '一个字符串';
intval($str);// intval()函数并不改变原值,返回一个被转化的整型值
var_dump($str);//  输出:string(15) "一个字符串"
var_dump(intval($str));//  输出:int(0)

var_dump(7 / 4);// 两个整型相除无法得到一个整型结果时,输出:float(1.75)
var_dump(9 / 3);// 输出:int(3)

var_dump((int)false);// 布尔值false转换为整型时值为 0
var_dump((int)true);// 布尔值true转换为整型时值为 1

$float = 9.22e+18 + 2.1;
var_dump($float);// float(9.22E+18)
var_dump((int)$float);// 输出:int(9220000000000000000)

$float = 1.8446744e+19;// 2的64次幂
var_dump($float);// float(1.8446744E+19)
var_dump((int)$float);// 输出:int(-73709551616)

$int = 2 ** 64;// 2的64次幂
var_dump($int);// 输出:float(1.844674407371E+19)
var_dump((int)$int);// 输出:int(0)

由上面的代码可知,浮点数转换为整型时容易导致许多不可预见的错误,需要慎重使用。

Float:浮点型

浮点型,也叫浮点数 Float 、双精度数 Double 或实数 Real 。通常用来表示带小数部分的数字,或者指数形式。例如下方代码:

<?php

// 小数
$float = 3.14159;
// 指数
$exponent = 2 ** 65;// 超出 Integer 的最大范围(PHP_INT_MAX)时,自动转为float类型

// 检测类型:var_dump()
var_dump($float);// 输出:float(3.14159)
var_dump($exponent);// 输出:float(3.6893488147419E+19)

$exponent = 3.141592e+10;// 科学计数法
var_dump($exponent);// 输出:float(31415920000)

由于浮点数的精度有限,字长与平台相关,所以永远不要相信浮点数结果精确到了最后一位,不要试图使用浮点数进行精密的计算。可以看下方示例代码:

<?php

$x = 1.234567;
$y = 1.234568;
var_dump($x == $y);// 输出:bool(false),正确期望
var_dump($y - $x);// 输出:float(1.0000000001398E-6)即 0.00000010000000001398 而不是正确的0.000001

$x = (0.1 + 0.7) * 10;
var_dump($x);// 输出:float(8)
var_dump(floor($x));// 输出:float(7)。其中floor()返回不大于 value 的最接近的整数,舍去小数部分取整。这代表$x不等于8.0
var_dump($x == 8.0);// 输出:bool(false)

如果进行金融或是数学方面等需要高精度的运算,应该使用任意精度数学函数或者gmp函数(未来会讲到这两类函数,这里先略过不提)。

String:字符串

字符串由一系列字符组成,每个字符等同于一个字节,string最大可达到2GB

表示方法可看下方示例代码:

<?php

$str = '我是一个字符串,由单引号包裹';
$str = '如果需要输出单引号本身,使用反斜杠对其转义,就像这样\',看看会输出什么';
// $str = '如果不使用反斜杠,会造成错误',你可以试试看(英文输入法状态下的特殊符号);
$str = '你好\n';// \n表示一个换行符
echo $str;// 输出:你好\n
echo PHP_EOL;

$str = "我是一个由双引号包裹的字符串";
$val = '极速数据';
$num = 666;
$arr = array(
    '我是数组的一个元素',
    '好巧,我是数组的另一个元素',
    '我猜下一个元素是数字',
    666,
    '楼楼上,你猜对了',
    '笔者很想写很多个数组元素',
);
// $str = "$val666";
// echo $str;// 输出:Undefined variable: val666
$str = "这句话里直接插入了变量$val 和另一个变量$num \n、一个数组元素{$arr[5]}以及一个换行符\n";
echo $str;
/* 输出:
这句话里直接插入了变量极速数据 和另一个变量666
、一个数组元素笔者很想写很多个数组元素以及一个换行符
*/

$here = <<<HERE
一个heredoc句法结构的字符串,
使用三个小于号+一个标识符(这里是HERE)表示开始,
然后换行,中间是字符串,
末尾以标识符顶行写(必须)
$val $num
通常用来引入一段带标记的长文本(例如HTML内容)\n
HERE;
print($here);
/* 输出:
一个heredoc句法结构的字符串,
使用三个小于号+一个标识符(这里是HERE)表示开始,
然后换行,中间是字符串,
末尾以标识符顶行写(必须)
极速数据 666
通常用来引入一段带标记的长文本(例如HTML内容)
*/

$now = <<<'NOW'
一个nowdoc句法结构的字符串,
使用三个小于号+一个被单引号括起来的标识符(这里是'NOW')表示开始,
然后换行,中间是字符串,
末尾以标识符顶行写(必须)
通常用来引入一段带标记的长文本(例如HTML内容)\n
NOW;
print($now);
/* 输出:
一个nowdoc句法结构的字符串,
使用三个小于号+一个被单引号括起来的标识符(这里是'NOW')表示开始,
然后换行,中间是字符串,
末尾以标识符顶行写(必须)
通常用来引入一段带标记的长文本(例如HTML内容)\n
*/

字符串与其他类型相互转换

其他数据类型要转换为字符串可以通过在其值前面加上(string)进行强制类型转换,或者使用strval()函数。例如下方代码:

<?php

// 类型转换

// 布尔值:true为1,false为0
$boolean = true;
var_dump((string)$boolean);// 输出:string(1) "1"

// 整型
$int = 666;
var_dump(strval($int));// 输出:string(3) "666"
var_dump((string)$int);// 输出:string(3) "666"

// 浮点数
$float = 0.89878;
var_dump(strval($float));// 输出:string(7) "0.89878"
$float = 89878e-5;
var_dump(strval($float));// 输出:string(7) "0.89878"

大部分的 PHP 值都可以通过转化为字符串后进行保存,被称为序列化(串行化),使用serialize()函数实现(使用该函数序列化后的结果,可以通过使用unserialize()反序列化得到序列化之前的结果)。

PHP 中有许多操作字符串的函数,在开发时经常会用到的比如查找某个特定字符第一次出现的位置(函数strpos())、字符串转数组(函数str_split())、获取字符串长度(函数strlen())等。后续我们将根据需求来详细讲解这些函数。


好的,关于数据类型的四种标量类型就讲到这里,之后我们将讲解三种复合类型