Другое

Максимальное безопасное целое число в JavaScript: объяснение

Узнайте о лимите Number.MAX_SAFE_INTEGER в JavaScript, его определении в спецификации ECMAScript, практических последствиях и альтернативах для работы с большими числами.

Каково максимальное целочисленное значение в JavaScript, которое может быть представлено без потери точности? Определено ли это значение в спецификации языка, и различается ли оно в разных браузерах или JavaScript-движках?

Максимальное целочисленное значение в JavaScript, которое можно представить без потери точности, — это 9007199254740991 (9 квадриллионов), что равно 25312^{53} - 1. Это значение определено в спецификации языка ECMAScript и стандартизировано во всех современных браузерах и движках JavaScript, что делает его единым пределом независимо от среды. Вы можете получить доступ к этому значению через константу Number.MAX_SAFE_INTEGER, а для более крупных целых чисел JavaScript теперь поддерживает тип BigInt, представленный в ES2020.

Что такое максимальное безопасное целое число в JavaScript?

Максимальное безопасное целое число в JavaScript — это 9007199254740991, которое можно программно получить с помощью встроенной константы Number.MAX_SAFE_INTEGER. Это представляет собой наибольшее целое число, которое можно точно представить в виде числа с плавающей запятой двойной точности IEEE-754 без потери точности.

javascript
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991

Математически это значение равно 25312^{53} - 1, где показатель степени 53 получается из 52-битной мантиссы плюс неявный ведущий бит в формате двойной точности IEEE 754. Это означает, что JavaScript может безопасно представлять все целые числа в диапазоне от -(2^53 - 1) до 2^53 - 1.

Интересно, что это число примерно равно 9 квадриллионам (9,007,199,254,740,991), что может показаться очень большим, но становится актуальным при работе с большими наборами данных, криптографических вычислениях или уникальных идентификаторах, превышающих этот диапазон.

Почему JavaScript имеет это ограничение?

Это ограничение связано с использованием JavaScript формата чисел с плавающей запятой двойной точности, как указано в стандарте IEEE 754. Этот формат представляет числа с использованием 64 бит, которые распределяются следующим образом:

  • 1 бит для знака
  • 11 бит для показателя степени
  • 52 бита для мантиссы (значащей части)

Ограничение точности возникает из-за того, что числа с плавающей запятой имеют фиксированное количество бит для представления мантиссы. При работе с целыми числами, превышающими 25312^{53} - 1, не хватает бит для уникального представления каждого возможного целочисленного значения, что приводит к округлению некоторых чисел или потере точности.

Как объясняется на Mozilla Developer Network, “JavaScript использует числа в формате двойной точности с плавающей запятой, как указано в IEEE 754, и может безопасно представлять числа только в диапазоне от -(2^53 - 1) до 2^53 - 1”.

Это не уникально для JavaScript — это фундаментальная характеристика того, как работает арифметика с плавающей запятой в большинстве языков программирования, использующих представление IEEE 754.

Как это значение определено в спецификации языка?

Number.MAX_SAFE_INTEGER формально определен в спецификации ECMAScript, конкретно в ECMAScript 2015 (ES6). Согласно спецификации, эта константа должна иметь значение 9007199254740991, что равно 25312^{53} - 1.

Введение этой константы было частью более широкого улучшения объекта Number в JavaScript в ES6, которое также добавило связанные функции, такие как:

  • Number.MIN_SAFE_INTEGER (-9007199254740991)
  • метод Number.isSafeInteger()
  • метод Number.isInteger()
  • метод Number.isFinite()

Как отмечается в обсуждениях спецификации ECMAScript, первоначально существовала некоторая путаница в терминологии, но спецификация четко определяет, что хотя 2532^{53} точно представимо, оно не считается “безопасным”, потому что следующее целое число не может быть представлено уникально.

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

Совместимость с браузерами и согласованность движков

Number.MAX_SAFE_INTEGER широко поддерживается во всех современных браузерах и движках JavaScript, так как он является частью стандарта ECMAScript с ES6 (2015). Согласно данным Can I use, поддержка включает:

  • Chrome 19+ (2012)
  • Firefox 15+ (2012)
  • Safari 9+ (2015)
  • Edge 12+ (2015)
  • Node.js 0.12+ (2015)

Критически важно, что значение не различается в разных браузерах или движках JavaScript, поскольку оно определяется спецификацией языка, а не является специфичным для реализации. Независимо от того, запускаете ли вы JavaScript в Chrome, Firefox, Safari, Node.js, Deno или Bun, Number.MAX_SAFE_INTEGER всегда будет возвращать 9007199254740991.

Эта согласованность является одним из ключевых преимуществ наличия спецификации языка, определяющей эти константы, а не оставляющей их на усмотрение отдельных реализаций движков. Как отмечает Codecademy, эта константа представляет “наибольшее целое число, которое можно безопасно представить с использованием типа Number без потери точности” во всех совместимых средах.

Практические последствия при работе с большими числами

При работе с целыми числами, которые приближаются или превышают Number.MAX_SAFE_INTEGER, разработчики должны быть осведомлены о нескольких практических последствиях:

Потеря точности

За пределами этого предела целые числа могут потерять точность. Например:

javascript
const max = Number.MAX_SAFE_INTEGER;
console.log(max + 1 === max + 2); // true! Оба выражения дают одинаковый результат
console.log(max + 1); // 9007199254740992
console.log(max + 2); // 9007199254740992 - тот же результат!
console.log(max + 3); // 9007199254740993

Математические операции

Базовые арифметические операции могут давать неожиданные результаты:

javascript
const large = Number.MAX_SAFE_INTEGER;
console.log(large - 1 === large); // false
console.log(large + 1 === large); // true!
console.log(large * 2); // 18014398509481984 (точно)
console.log(large * 2 + 1); // 18014398509481984 (то же самое, что и выше!)

Индексы массивов и свойства объектов

Хотя движки JavaScript могут обрабатывать индексы массивов, превышающие этот предел в некоторых случаях, это не является надежным поведением. Свойства объектов, используемые в качестве индексов массивов, должны оставаться в пределах безопасного диапазона целых чисел.

Уникальные идентификаторы

При генерации уникальных идентификаторов (например, идентификаторов базы данных или временных меток) учтите, что значения, превышающие Number.MAX_SAFE_INTEGER, могут не быть уникальными из-за потери точности.

Альтернативы для работы с более крупными целыми числами

Для приложений, которым нужно работать с целыми числами, превышающими Number.MAX_SAFE_INTEGER, JavaScript представил BigInt в ES2020:

javascript
// До BigInt
const largeNum = Number.MAX_SAFE_INTEGER * 2; // 18014398509481984
console.log(largeNum + 1 === largeNum); // true (потеря точности)

// С BigInt
const bigIntNum = BigInt(Number.MAX_SAFE_INTEGER) * 2n;
console.log(bigIntNum + 1n === bigIntNum); // false (без потери точности)
console.log(bigIntNum + 1n); // 18014398509481985n

BigInt позволяет использовать целые числа произвольной точности, хотя с некоторыми ограничениями:

  • Нельзя смешивать с обычными числами в операциях
  • Нет битовых операций кроме AND, OR, XOR, NOT
  • Нельзя использовать с встроенными функциями Math
  • Некоторые соображения при сериализации JSON

Как указано в документации Mozilla, “Для более крупных целых чисел рассмотрите возможность использования BigInt.”

Другие альтернативы включают:

  • Строковое представление больших чисел
  • Внешние библиотеки для арифметики произвольной точности
  • Разделение больших чисел на несколько меньших целых чисел

Заключение

Максимальное безопасное целое число JavaScript 9007199254740991 (25312^{53} - 1) является фундаментальным ограничением языка, связанным с его представлением чисел с плавающей запятой двойной точности IEEE 754. Это значение последовательно определено во всех браузерах и движках JavaScript через спецификацию ECMAScript, обеспечивая предсказуемое поведение независимо от среды выполнения.

При работе с большими числами разработчикам следует:

  • Всегда проверять диапазоны целых чисел с помощью Number.isSafeInteger()
  • Рассмотреть возможность использования BigInt для значений, превышающих Number.MAX_SAFE_INTEGER
  • Осознавать, что арифметические операции за этим пределом могут давать неожиданные результаты
  • Тестировать граничные случаи в вашем конкретном случае использования, чтобы убедиться, что требования к точности выполнены

Введение BigInt в ES2020 обеспечивает надежное решение для приложений, требующих целых чисел произвольной точности, в то время как Number.MAX_SAFE_INTEGER остается важной константой для понимания пределов обычных числовых операций в JavaScript.

Источники

  1. Mozilla Developer Network - Number.MAX_SAFE_INTEGER
  2. Stack Overflow - JavaScript’s highest integer value without losing precision
  3. Codecademy - JavaScript Number.MAX_SAFE_INTEGER
  4. Vultr Documentation - Maximum Safe Integer in JavaScript
  5. Can I use - ES6 Number enhancements
  6. ESDiscuss - Number.MAX_SAFE_INTEGER specification discussion
  7. W3cubDocs - Number.MAX_SAFE_INTEGER
  8. Tutorialspoint - JavaScript’s highest integer value
  9. ECMAScript 2020 Features - BigInt introduction
  10. GitHub - ECMAScript Features cheatsheet
Авторы
Проверено модерацией
Модерация