log1p

Computes log(1 + x) accurately even when x is very close to zero.

Signature
log1p(float $num): float
  • Added in PHP 4.1.0

Parameters

ParameterTypeDescription
$numfloatThe value to add to 1 before taking the natural logarithm.

Return value

floatlog(1 + num), computed in a way that stays accurate for values of num close to zero.

log1p($x) computes log(1 + $x) — but accurately for small $x. Note carefully what it takes: the x, not the 1 + x.

The problem it solves

A double has about 16 significant digits near 1.0. If $x is 1e-16 then 1 + $x rounds straight back to 1.0 before log() ever sees it, and you get 0.0 instead of roughly 1e-16. Even at 1e-9, where the addition survives, you have already discarded half of your significant digits. The error is invisible in a single call and catastrophic after a few million of them, which is exactly the situation where the number is small in the first place.

When to reach for it

Any time the argument to a logarithm is "1 plus something small": per-period interest and growth rates, continuously compounded returns, log-probabilities near certainty, relative error terms, and statistical likelihoods. Its inverse partner is expm1(), which computes exp($x) - 1 with the same trick; use them together so precision survives the round trip.

For arguments well away from zero log1p($x) and log(1 + $x) agree, so there is no cost to defaulting to log1p(). log1p(-1) is -INF, and anything below -1 returns NAN.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Converting a tiny per-period interest or growth rate into a continuously compounded rate.
  • Accumulating log-likelihoods where individual probabilities sit very close to 1.
  • Computing log(1 + relative_error) in numerical analysis without losing digits.
  • Handling per-second or per-millisecond rates that get raised to very large powers.

Frequently asked questions

When should I use log1p instead of log?

Whenever the argument would be 1 plus a small number. Below roughly 1e-8 the expression log(1 + $x) has already lost half its significant digits, while log1p($x) keeps all of them.

Does log1p take x or 1 + x?

It takes x. log1p(0.05) computes log(1.05). Passing log1p(1 + $x) computes log(2 + $x) instead, which is the classic bug with this function.

What is the inverse of log1p?

expm1(), which computes exp($x) - 1 accurately near zero. expm1(log1p($x)) round-trips small values that exp(log(1 + $x)) - 1 would destroy.

More examples

Comparing against the true value

The Taylor series x - x^2/2 + x^3/3 is the mathematically correct value for such a small argument. log1p() matches it to every printed digit; log(1 + r) diverges around the ninth significant figure, because the information was already lost in the addition before the logarithm was taken.

Example · php
<?php
$r = 1.0e-10;

printf("log(1 + r) = %.18e\n", log(1 + $r));
printf("log1p(r)   = %.18e\n", log1p($r));
printf("series     = %.18e\n", $r - $r ** 2 / 2 + $r ** 3 / 3);

Round-tripping with expm1()

log1p() and expm1() are designed as a pair, so taking the logarithm and undoing it returns the original value essentially intact. The naive route through log() and exp() loses several significant digits in each direction, and the subtraction of 1 at the end throws away most of what survived.

Example · php
<?php
$small = 2.5e-12;

printf("original:    %.18e\n", $small);
printf("log1p/expm1: %.18e\n", expm1(log1p($small)));
printf("log/exp:     %.18e\n", exp(log(1 + $small)) - 1);

Discussion

  • Be the first to comment on this lesson.