log1p()
Функция log1p() в PHP вычисляет натуральный логарифм от 1 плюс число с высокой точностью для малых значений.
Функция log1p() в PHP вычисляет натуральный логарифм от 1 + x, записываемый как ln(1 + x), таким образом, чтобы результат оставался точным при значениях x, очень близких к нулю. На этой странице рассматриваются синтаксис функции, проблема точности, которую она решает, значения на границах её области определения и случаи, когда стоит использовать её вместо обычного log().
Синтаксис
log1p(float $num): float$num— значение, прибавляемое к 1. Для получения конечного результата должно быть больше-1.- Возвращаемое значение —
float, равное натуральному логарифму (по основаниюe) от1 + $num.
Что делает log1p()
Математически log1p($num) идентична log(1 + $num). Разница заключается в числовой точности. Числа с плавающей запятой имеют ограниченную точность, поэтому при вычислении 1 + $num для очень маленького $num большинство значимых цифр $num теряется при сложении ещё до применения логарифма. Это явление называется катастрофической отменой.
log1p() реализована так, чтобы вычислять ln(1 + x) напрямую, без промежуточного суммирования, поэтому эти цифры сохраняются. Для малых входных значений это правильный инструмент; для больших значений обе функции дают одинаковый результат.
Простой пример
Передаём очень маленькое значение в log1p() и выводим результат. Вывод — натуральный логарифм от 1.0001, выраженный в научной нотации (9.9995...E-5 означает 0.000099995...).
Почему log1p() лучше log(1 + $x) для малых значений
Сравним два подхода на одном и том же малом входном значении:
<?php
$x = 1e-15;
echo log1p($x), "\n"; // 1.0E-15 (accurate)
echo log(1 + $x), "\n"; // 1.1102230246252E-15 (wrong)
?>Ожидаемый ответ — приблизительно 1e-15. log1p() возвращает его почти точно, тогда как log(1 + $x) примерно на 11% больше, поскольку 1 + 1e-15 уже плохо округляется в двоичной арифметике двойной точности. Чем меньше входное значение, тем больше относительная погрешность наивного подхода — именно поэтому и существует log1p().
Область определения и граничные случаи
Аргумент должен быть больше -1. Посмотрим, как ведут себя границы:
<?php
var_dump(log1p(0)); // float(0) — ln(1) = 0
var_dump(log1p(M_E - 1)); // float(1) — ln(e) = 1
var_dump(log1p(-1)); // float(-INF) — ln(0) is negative infinity
var_dump(log1p(-2)); // float(NAN) — undefined: 1 + (-2) = -1 < 0
?>log1p(0)возвращает0, так какln(1) = 0.- При
$num = -1внутреннее значение равно0, и логарифм стремится к минус бесконечности (-INF). - При
$num < -1результат равенNAN(не число), поскольку логарифм от неположительного числа не определён для вещественных чисел.
Защитите код от неверных входных данных перед вызовом функции:
<?php
function safeLog1p(float $num): ?float
{
if ($num <= -1) {
return null; // outside the valid domain
}
return log1p($num);
}
var_dump(safeLog1p(0.5)); // float(0.4054651081081644)
var_dump(safeLog1p(-1.5)); // NULL
?>Когда использовать
log1p() — это оптимизация точности, поэтому она особенно полезна при работе с величинами, близкими к нулю:
- Финансы — преобразование малой процентной или темпа роста
rв непрерывно начисляемую ставку с помощьюlog1p($r). - Статистика и машинное обучение — вычисление лог-вероятностей или лог-правдоподобий, где отдельные значения очень малы.
- Научные вычисления — любая формула вида
ln(1 + x), гдеxможет быть малым.
Для обычных входных значений, далёких от нуля, log() вполне подходит; обе функции возвращают практически одинаковый результат. Обратная операция — восстановление x из log1p(x) — это expm1(), которая вычисляет e^x - 1 с таким же преимуществом в точности.
Связанные функции
log()— натуральный логарифм или логарифм по произвольному основанию.log10()— десятичный логарифм.exp()—eв степени (обратная функция кlog()).expm1()— точное вычислениеe^x - 1; обратная функция кlog1p().- PHP Math Functions — обзор математической библиотеки PHP.
Заключение
log1p() вычисляет ln(1 + x), сохраняя точность для входных значений, близких к нулю, где наивный log(1 + $x) теряет точность. Помните, что аргумент должен быть больше -1, что значение -1 даёт -INF, а значения ниже -1 возвращают NAN. Используйте эту функцию в финансовых, статистических и научных вычислениях при работе с малыми значениями.