sprintf() 是 PHP 格式化字串的核心函數,依據格式字串將參數轉為指定格式並回傳(不直接輸出)。本文重點解析浮點數格式化、寬度與精度控制,以及整數與浮點數參數傳遞的陷阱。
sprintf(string $format, mixed ...$values): string
$format:格式字串,包含一般文字與格式規範(以 % 開頭)。$values:對應格式規範的參數值。| 規範 | 說明 | 範例 |
|---|---|---|
%s | 字串 | sprintf('%s', 'hello') // 'hello' |
%d / %u | 有號/無號十進位整數 | sprintf('%d', -10) // '-10' |
%f / %F | 浮點數(區分大小寫處理非數值) | sprintf('%f', 3.14) // '3.140000' |
%e / %E | 科學記號 | sprintf('%e', 1000) // '1.000000e+3' |
%x / %X | 十六進位(小寫/大寫) | sprintf('%x', 255) // 'ff' |
%% | 字面 % 符號 | sprintf('100%%') // '100%' |
%[flags][width][.precision]f<?php
$num = 3.1415926;
// 預設:小數 6 位,無寬度限制
echo sprintf('%f', $num); // "3.141593" (四捨五入)
// 指定總寬度 9、小數 3 位,右對齊(前面補空格)
echo sprintf('%9.3f', $num); // " 3.142"
// 指定總寬度 9、小數 3 位,左對齊(後面補空格)
echo sprintf('%-9.3f', $num); // "3.142 "
// 僅指定精度,不限寬度
echo sprintf('%.3f', $num); // "3.142"
// 0 填充寬度(前面補 0)
echo sprintf('%09.3f', $num); // "0003.142"
// 強制顯示正負號
echo sprintf('%+f', $num); // "+3.141593"
echo sprintf('%+f', -$num); // "-3.141593"
?>
%f 格式<?php
$num = 100; // 整數
// 錯誤示範:直接傳整數給 %f
$result1 = sprintf('%.2f', $num);
// 結果:"100.00" (看似正確,但行為未定義)
// 正確做法:明確轉型為 float
$result2 = sprintf('%.2f', (float)$num);
// 結果:"100.00" (明確語意)
// 更明確:使用浮點數字面值
$result3 = sprintf('%.2f', 100.0);
?>
原因:sprintf 為 C 風格可變參數函數,格式字串在執行期解析。若格式為 %f 但實際傳入整數,屬於未定義行為(Undefined Behavior),視平台/編譯器可能導致錯誤結果或崩潰。務必確保參數型別與格式規範匹配。
<?php
function formatCurrency(float $amount, string $currency = 'TWD', int $decimals = 2): string {
$sign = $amount < 0 ? '-' : '';
$abs = abs($amount);
// 整數部分加千分位,小數固定位數
return $sign . $currency . ' ' . number_format($abs, $decimals, '.', ',');
}
echo formatCurrency(1234567.89); // "TWD 1,234,567.89"
echo formatCurrency(-99.5); // "-TWD 99.50"
?>
註:純貨幣格式化建議用 NumberFormatter (intl 擴展) 支援地區化。
| 函數 | 輸出方式 | 用途 |
|---|---|---|
sprintf() | 回傳字串 | 組合字串、記錄日誌、產生 SQL、快取鍵 |
printf() | 直接輸出 | 簡單輸出、除錯 |
vsprintf() | 回傳字串 | 參數為陣列 vsprintf($fmt, $args) |
vprintf() | 直接輸出 | 參數為陣列 |
%[width].[precision]f 控制浮點數顯示格式。%f、%e、%g。NumberFormatter。sprintf($userInput, ...)。