當前位置: 首頁> 最新文章列表> 使用pack() 打包浮點數的正確方式

使用pack() 打包浮點數的正確方式

M66 2025-06-04

1. pack()函數簡介

pack()函數的基本語法如下:

 string pack(string $format, mixed ...$values)
  • $format :格式字符串,定義了後面傳入值的打包方式。

  • $values :要打包的數據列表。

例如, pack('C', 65)會返回一個ASCII 值為65 的字節(即字符A )。


2. 浮點數格式符號

對於浮點數, 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. 示例:打包浮點數為二進製字符串

假設我們要將浮點數3.14打包為網絡傳輸所需的二進制流(一般要求使用大端):

 <?php
$float = 3.14;
$binary = pack('G', $float); // 打包為大端的32位浮點數
echo bin2hex($binary); // 輸出十六進制結果查看
?>

輸出(可能類似):

 4048f5c3

這個值可以在其他支持IEEE 754 標準的語言中解析回來為3.14。


4. 解包驗證

我們可以使用unpack()驗證上面打包的值是否正確:

 <?php
$binary = pack('G', 3.14);
$result = unpack('Gfloat', $binary);
echo $result['float']; // 輸出 3.14
?>

5. 實際應用:浮點數打包並上傳

假設你正在構建一個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);

6. 小貼士

  • 如果對浮點數精度要求較高,請使用d (64 位雙精度)。

  • 跨平台通信時,務必統一字節序,推薦使用G (32 位大端)或E (64 位大端)。

  • 使用bin2hex()unpack()來調試打包結果。

  • 不要在未明確知道字節序的情況下使用默認的fd