Log1p: примеры (PHP)
log1p(float $num): floatФункция log1p() вычисляет натуральный логарифм от значения (1 + число). Эта операция выполняется таким способом, который обеспечивает высокую точность даже при очень малых значениях аргумента, близких к нулю.
Основное применение — математические и статистические расчеты, где требуется точное вычисление логарифма для величин, незначительно отличающихся от единицы. Функция помогает избежать потери точности при сложении единицы и очень маленького числа в арифметике с плавающей запятой.
Аргументы функции:
- $num (float) — единственный обязательный параметр. Число, к которому прибавляется единица перед вычислением логарифма. Значение должно быть больше -1.
echo log1p(0);0
echo log1p(1.5);0.91629073187416
echo log1p(-0.5);-0.69314718055995
var_dump(log1p(-1));float(NAN)
- log() — вычисляет натуральный логарифм. Принимает один или два аргумента. Во втором случае можно указать основание. Используется, когда не требуется особая точность при вычислении log(1 + x).
- log10() — вычисляет десятичный логарифм (по основанию 10). Подходит для задач, связанных с порядком величины.
- expm1() — выполняет обратную операцию: вычисляет exp(x) - 1 с высокой точностью для малых x. Часто используется в паре с log1p().
- Выбор функции: log1p() предпочтительнее при работе с очень малыми числами (например, в финансовых расчетах, теории вероятностей). Для обычных вычислений логарифма достаточно log().
import math
print(math.log1p(0.001))0.000999500333083533
console.log(Math.log1p(0.001));0.000999500333083533
SELECT LOG1P(0.001);0.000999500333083533
Функции в этих языках аналогичны реализации в PHP 8, но могут отличаться деталями округления или обработки особых случаев (например, -1). В Python и JavaScript функция также возвращает особые значения (NaN, Infinity) для недопустимых аргументов.
$result = log1p(-2);
var_dump($result);float(NAN)
Функция возвращает NAN (Not a Number), что может нарушить последующие вычисления, если не проверить результат.
// Неправильное понимание: ожидание log(0.001) вместо log(1 + 0.001)
$smallNumber = 0.001;
echo 'log1p: ' . log1p($smallNumber) . "\n";
echo 'log: ' . log(1 + $smallNumber) . "\n";log1p: 0.00099950033308353 log: 0.00099950033308353
Хотя для больших чисел разница может быть незаметна, для очень малых значений прямое сложение с единицей теряет точность.
В PHP 8.0 функция log1p() не претерпела значительных изменений по сравнению с предыдущими версиями. Она была стабильной и в PHP 7.x. Однако, стоит отметить, что с увеличением версий PHP общие улучшения производительности и стабильности математических функций могли коснуться и log1p(). Специфических изменений в поведении или сигнатуре функции с выходом PHP 8.0 не задокументировано.
function logNormalCDF($x, $mu, $sigma) {
if ($x <= 0) return 0.0;
$z = (log($x) - $mu) / $sigma;
return 0.5 * (1 + erf($z / sqrt(2)));
}
// Используем log1p для повышения точности при малых значениях
function log1pErf($x) {
return log1p(erf($x));
}
// Пример с малой погрешностью
$smallVal = 1e-10;
echo 'log1p результат: ' . log1p($smallVal) . "\n";
echo 'Обычный log: ' . log(1 + $smallVal) . "\n";log1p результат: 9.9999999995E-11 Обычный log: 9.9999999995E-11
// Сумма логарифмов с использованием log1p для стабильности
function sumLogs(array $values) {
$sum = 0.0;
foreach ($values as $value) {
// Для значений близких к нулю используем log1p
if (abs($value) < 0.001) {
$sum += log1p($value);
} else {
$sum += log(1 + $value);
}
}
return $sum;
}
$data = [0.0001, 0.0002, 0.0003];
echo sumLogs($data);0.00059985002749938
// Когда вероятность близка к 1, log(p) может быть неточным
$probability = 0.999999;
$logProb = log1p($probability - 1); // Эквивалентно log(p), но точнее
echo 'log1p: ' . $logProb . "\n";
echo 'log: ' . log($probability) . "\n";log1p: -1.0000000001536E-6 log: -1.0000000001536E-6
for ($i = 0; $i < 5; $i++) {
$x = $i * 0.0001;
printf("log1p(%f) = %.15f\n", $x, log1p($x));
}log1p(0.000000) = 0.000000000000000 log1p(0.000100) = 0.000099995000333308 log1p(0.000200) = 0.000199980006666827 log1p(0.000300) = 0.000299955015002425 log1p(0.000400) = 0.000399920026670843