log1p() 函数返回 log(1 + num),即使 num 的值接近零也能保证结果的精度。当 num 非常小时,直接使用 log(1 + $num) 会由于浮点精度丢失而产生较大误差,而 log1p() 可以精确计算。
log1p(float $num): float
| 参数 | 描述 |
|---|---|
num |
必需。规定要计算对数的参数,必须大于 -1。 |
返回 log(1 + num) 的值(浮点数)。如果 num ≤ -1,返回 NAN(非数字)。
<?php
echo log1p(0) . "<br>"; // 0
echo log1p(1) . "<br>"; // 约 0.69314718055995 (log(2))
echo log1p(9) . "<br>"; // 约 2.302585092994 (log(10))
echo log1p(-0.5) . "<br>"; // 约 -0.69314718055995 (log(0.5))
?>
输出:
0
0.69314718055995
2.302585092994
-0.69314718055995
<?php
$x = 1e-15;
$direct = log(1 + $x);
$accurate = log1p($x);
echo "x = $x<br>";
echo "log(1 + x) = $direct<br>";
echo "log1p(x) = $accurate<br>";
echo "差值 = " . ($accurate - $direct);
?>
输出:
x = 1.0E-15
log(1 + x) = 1.1102230246252E-15
log1p(x) = 1.0E-15
差值 = -1.102230246252E-16
可以看到,log1p() 的结果更精确(接近 1e-15),而直接计算因浮点误差产生了偏差。
<?php
// 计算连续复利下的实际年利率
function effectiveRate($nominalRate, $compoundingPerYear) {
// 每个复利周期的利率
$periodRate = $nominalRate / $compoundingPerYear;
// 使用 log1p 精确计算连续复利等效利率
return exp($compoundingPerYear * log1p($periodRate)) - 1;
}
$nominal = 0.05; // 名义年利率 5%
$monthly = effectiveRate($nominal, 12);
$daily = effectiveRate($nominal, 365);
echo "名义利率 $nominal<br>";
echo "按月复利实际年利率: " . round($monthly * 100, 6) . "%<br>";
echo "按日复利实际年利率: " . round($daily * 100, 6) . "%";
?>
输出:
名义利率 0.05
按月复利实际年利率: 5.11619%
按日复利实际年利率: 5.12675%
num 必须大于 -1。如果 num ≤ -1,函数返回 NAN 并产生一个警告(PHP 7+)。num 接近零时,log1p() 比 log(1 + $num) 更精确,避免因浮点舍入导致的有效数字丢失。