Learn JavaScript

Math.log1p() - метод для вычисления натурального логарифма от 1 + x в JavaScript

Math.log1p() вычисляет натуральный логарифм от 1 + x.

Проще всего запомнить так: Math.log1p(x) - это почти Math.log(1 + x), но точнее на очень маленьких значениях.

Синтаксис

Math.log1p(x)

x - число, к которому сначала прибавляют 1, а потом берут натуральный логарифм.

Что делает Math.log1p()

Метод вычисляет значение по формуле:

log(1 + x)

Примеры:

console.log(Math.log1p(0));   // 0
console.log(Math.log1p(1));   // 0.6931471805599453
console.log(Math.log1p(-0.5)); // -0.6931471805599453

То есть:

  • Math.log1p(0) даёт log(1)
  • Math.log1p(1) даёт log(2)
  • Math.log1p(-0.5) даёт log(0.5)

Что возвращает Math.log1p()

Math.log1p() возвращает число типа number.

const result = Math.log1p(2);

console.log(result);        // 1.0986122886681096
console.log(typeof result); // "number"

Почему Math.log1p(0) равно 0

Это видно прямо из формулы.

console.log(Math.log1p(0)); // 0

Потому что:

  • 1 + 0 = 1
  • log(1) = 0

Положительные и отрицательные значения

Если x больше 0, результат будет положительным.

console.log(Math.log1p(1)); // 0.6931471805599453
console.log(Math.log1p(4)); // 1.6094379124341003

Если x находится между -1 и 0, результат будет отрицательным.

console.log(Math.log1p(-0.5));  // -0.6931471805599453
console.log(Math.log1p(-0.75)); // -1.3862943611198906

Это нормальное поведение, а не ошибка.

Граница при x = -1

Здесь находится важный край области допустимых значений.

console.log(Math.log1p(-1)); // -Infinity

Потому что:

  • 1 + (-1) = 0
  • log(0) = -Infinity

Что будет при x < -1

Если x меньше -1, результатом будет NaN.

console.log(Math.log1p(-2)); // NaN

Потому что тогда 1 + x становится отрицательным числом, а натуральный логарифм отрицательного значения в обычных числах JavaScript не вычисляется.

Math.log1p() и Math.log(1 + x)

На первый взгляд кажется, что это одно и то же.

console.log(Math.log1p(2));    // 1.0986122886681096
console.log(Math.log(1 + 2));  // 1.0986122886681096

Для обычных значений результат часто совпадает.

Но Math.log1p() особенно полезен на очень маленьких числах, потому что считает точнее.

console.log(Math.log(1 + 1e-16)); // 0
console.log(Math.log1p(1e-16));   // 1e-16

Именно в этом и главный смысл метода: он нужен не только для короткой записи, но и для более точных вычислений.

Math.log1p() и Math.log()

Эти методы связаны, но делают не одно и то же.

console.log(Math.log(2));     // 0.6931471805599453
console.log(Math.log1p(1));   // 0.6931471805599453
  • Math.log(x) вычисляет log(x)
  • Math.log1p(x) вычисляет log(1 + x)

Если по формуле сначала нужно прибавить 1, обычно лучше сразу использовать Math.log1p().

Math.log1p() и Math.expm1()

Эти методы логически связаны как обратные операции.

console.log(Math.expm1(Math.log1p(5))); // 5
  • Math.log1p(x) делает log(1 + x)
  • Math.expm1(x) делает e^x - 1

Эту пару особенно удобно знать, если вы уже используете Math.expm1().

Без аргумента

Если вызвать Math.log1p() без аргумента, результатом будет NaN.

console.log(Math.log1p()); // NaN

Так происходит потому, что метод попытается обработать undefined как число.

Неявное приведение типов

Math.log1p() сначала пытается привести аргумент к числу.

console.log(Math.log1p("1"));   // 0.6931471805599453
console.log(Math.log1p(null));  // 0
console.log(Math.log1p(true));  // 0.6931471805599453
console.log(Math.log1p(undefined)); // NaN

На практике обычно лучше передавать в метод уже готовое число.

NaN и Infinity

Для специальных значений метод ведёт себя предсказуемо.

console.log(Math.log1p(NaN));       // NaN
console.log(Math.log1p(Infinity));  // Infinity
console.log(Math.log1p(-Infinity)); // NaN

Это полезно помнить:

  • Infinity даёт Infinity
  • -Infinity даёт NaN

Число не меняется

Math.log1p() не изменяет исходное значение. Он только возвращает новый результат.

const value = 1;
const result = Math.log1p(value);

console.log(value);  // 1
console.log(result); // 0.6931471805599453

Когда это полезно

Math.log1p() удобно использовать, когда:

  • нужно вычислить именно log(1 + x)
  • важна точность на очень маленьких значениях
  • формула уже записана в таком виде
  • вы хотите избежать лишней потери точности в вычислениях

Пример:

const x = 1e-16;

console.log(Math.log1p(x)); // 1e-16

Частые ошибки

Думать, что это просто Math.log(x)

console.log(Math.log(1));    // 0
console.log(Math.log1p(1));  // 0.6931471805599453

Один метод вычисляет log(x), другой - log(1 + x).

Не учитывать границу x = -1

console.log(Math.log1p(-1)); // -Infinity
console.log(Math.log1p(-2)); // NaN

При x = -1 результат ещё допустим, а при x < -1 уже нет.

Не знать про точность на маленьких числах

console.log(Math.log(1 + 1e-16)); // 0
console.log(Math.log1p(1e-16));   // 1e-16

Это как раз тот случай, ради которого метод и существует.

Быстрая памятка

  • Math.log1p(x) вычисляет log(1 + x)
  • метод возвращает number
  • Math.log1p(0) равно 0
  • при x = -1 результатом будет -Infinity
  • при x < -1 результатом будет NaN
  • Math.log1p(x) и Math.log(1 + x) часто дают похожий результат
  • на очень маленьких числах Math.log1p() точнее

Коротко

Math.log1p() - это стандартный способ вычислить натуральный логарифм от 1 + x в JavaScript. Главное, что стоит запомнить: метод особенно полезен тогда, когда важна точность на очень маленьких значениях, и именно этим он лучше простого Math.log(1 + x).