pack() 函数的基本语法如下:
string pack(string $format, mixed ...$values)
$format:格式字符串,定义了后面传入值的打包方式。
$values:要打包的数据列表。
例如,pack('C', 65) 会返回一个 ASCII 值为 65 的字节(即字符 A)。
对于浮点数,pack() 提供两个关键的格式符号:
f:将数据作为 32 位单精度浮点数 进行打包。
d:将数据作为 64 位双精度浮点数 进行打包。
但问题来了——字节序(endianness) 在不同平台上可能不同。在 pack() 中可以通过前缀来指定字节序:
f / d:使用主机字节序(可能是大端也可能是小端)
g:32 位浮点数,使用 小端 字节序(类似于 Intel 架构)
G:32 位浮点数,使用 大端 字节序
e:64 位浮点数,小端字节序
E:64 位浮点数,大端字节序
注意: g / G / e / E 是从 PHP 7.0 开始引入的。
假设我们要将浮点数 3.14 打包为网络传输所需的二进制流(一般要求使用大端):
<?php
$float = 3.14;
$binary = pack('G', $float); // 打包为大端的32位浮点数
echo bin2hex($binary); // 输出十六进制结果查看
?>
输出(可能类似):
4048f5c3
这个值可以在其他支持 IEEE 754 标准的语言中解析回来为 3.14。
我们可以使用 unpack() 验证上面打包的值是否正确:
<?php
$binary = pack('G', 3.14);
$result = unpack('Gfloat', $binary);
echo $result['float']; // 输出 3.14
?>
假设你正在构建一个 API,需要将多个浮点数打包上传:
<?php
$data = [1.23, 4.56, 7.89];
$binary = '';
foreach ($data as $num) {
$binary .= pack('G', $num); // 大端格式
}
// 将打包后的数据上传到服务端
$url = 'https://m66.net/upload-float-data';
$options = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/octet-stream\r\n",
'content' => $binary,
],
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
如果对浮点数精度要求较高,请使用 d(64 位双精度)。
跨平台通信时,务必统一字节序,推荐使用 G(32 位大端)或 E(64 位大端)。
使用 bin2hex() 或 unpack() 来调试打包结果。
不要在未明确知道字节序的情况下使用默认的 f 或 d。