Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  1. Главная
  2. Категории
  3. Языки программирования
  4. JavaScript
  5. Chrome 145 внедряет Math.sumPrecise: точные вычисления

Chrome 145 внедряет Math.sumPrecise: точные вычисления

Запланировано Прикреплена Закрыта Перенесена JavaScript
javascriptmath.sumpreciseточность вычислений
1 Сообщения 1 Постеры 55 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • hannadevH Не в сети
    hannadevH Не в сети
    hannadev
    написал в отредактировано
    #1

    В JavaScript наконец появился встроенный способ складывать числа без потери точности. Браузеры начинают поддерживать Math.sumPrecise() - метод, который решает одну из самых раздражающих проблем при работе с плавающей запятой. Если вы когда-то сталкивались с ситуацией, когда 0.1 + 0.2 дает 0.30000000000000004, то этот материал точно для вас.

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

    Почему стандартное складывание чисел ненадежно

    Чтобы понять суть проблемы, посмотрим на конкретный пример. Когда вы складываете числа в цикле, JavaScript использует 64-битное представление (формат IEEE 754). Это означает, что не все десятичные числа можно представить точно - они округляются до ближайшего возможного значения.

    Представьте, что вы складываете три числа: 1e20, 0.1 и -1e20. Логически результат должен быть 0.1, верно? Но посмотрите, что происходит на самом деле:

    let sum = 0;
    const numbers = [1e20, 0.1, -1e20];
    for (const number of numbers) {
      sum += number;
    }
    console.log(sum); // 0
    

    Результат равен 0, хотя должен быть 0.1. Почему? Потому что 1e20 + 0.1 не может быть представлено точно в 64-битном формате, поэтому промежуточный результат округляется до 1e20. Затем 1e20 + (-1e20) дает 0, и вот итоговый результат испорчен.

    Вот еще одна классическая проблема:

    console.log(0.1 + 0.2); // 0.30000000000000004
    

    Это происходит потому, что литералы 0.1 и 0.2 в JavaScript уже представляют математические значения, чуть большие, чем 0.1 и 0.2, и их сумма наиболее близко может быть представлена как 0.30000000000000004.

    Как Math.sumPrecise() решает проблему

    Метод Math.sumPrecise() использует более продвинутый алгоритм суммирования, который минимизирует потерю точности при промежуточных вычислениях. Вместо простого суммирования элементов подряд он применяет специальную стратегию для отслеживания и компенсации ошибок округления.

    Возьмем тот же пример с 1e20, 0.1 и -1e20:

    Math.sumPrecise([1e20, 0.1, -1e20]); // 0.1
    

    Теперь результат верный! Алгоритм гарантирует, что малые значения не теряются среди больших чисел. Это особенно важно, когда вы складываете много чисел разных масштабов - ситуация, частая в реальных приложениях.

    Поддержка браузерами и текущий статус

    Предложение Math.sumPrecise прошло долгий путь в TC39. Это фича на этапе 3 процесса стандартизации, что означает - готова к внедрению в браузеры. Но поддержка пока что неравномерна:

    Браузер Поддержка Версия
    Firefox Да Начиная с версии 137
    Safari Да Начиная с версии 26.2
    Chrome Нет Планируется в v147+
    Edge Нет На этапе рассмотрения

    Chrome начал работу над внедрением этой фичи, но еще не добавил ее в стабильный релиз. Если верить планам, она должна появиться в одной из ближайших версий браузера. Mozilla и Apple уже поддерживают эту функцию, что говорит о готовности стандарта.

    У разработчиков, которые пишут код для максимальной совместимости, пока нет выбора - придется использовать полифилл или продолжать складывать числа по-старому. Но для новых проектов и для браузеров с поддержкой это реальный плюс.

    Особенности использования Math.sumPrecise()

    Метод работает с итерируемыми объектами, то есть с любыми структурами, которые можно обойти в цикле - массивами, Set и другими. Он приемлет только настоящие числа (Number), не строки, не объекты. Если вы попытаетесь передать что-то другое, получите TypeError.

    Вот что важно учитывать при использовании:

    • Только числа: Метод будет выбросить исключение, если в массиве окажется что-то другое. Это отличается от Math.max() и Math.min(), которые пытаются преобразовать аргументы.
    • Пустой массив возвращает -0: Это выбрано потому, что -0 - аддитивная идентичность в числах с плавающей запятой. Это гарантирует, что Math.sumPrecise([]) + Math.sumPrecise(foo) всегда даст то же значение, что и Math.sumPrecise(foo).
    • Не работает с BigInt: Метод работает только с обычными числами (Number), не с BigInt. Это логично, потому что при смешивании типов возникла бы путаница.
    • Это статический метод: Вы вызываете его как Math.sumPrecise(), а не как someObject.sumPrecise().

    Где это особенно полезно

    Теперь встает вопрос - в каких ситуациях эта точность действительно критична? Есть несколько областей, где Math.sumPrecise() может спасти положение:

    • Финансовые приложения: Если вы считаете суммы платежей, налоги или проценты, ошибка в последнем знаке может привести к копейкам, которые потеряются. Банки и платежные системы особенно требовательны к точности.
    • Научные вычисления: В физике, математике и других науках накопление ошибок округления может привести к неверным выводам. Когда вы складываете результаты тысячи измерений, точность каждого суммирования имеет значение.
    • Аналитика больших датасетов: Если вы обрабатываете статистику по миллионам событий, небольшие ошибки суммирования могут исказить итоговые метрики.
    • Графика и вычислительная геометрия: Координаты, векторы и другие вычисления часто требуют высокую точность, чтобы результаты выглядели правильно.
    • Машинное обучение: Многие алгоритмы ML требуют точных вычислений при суммировании весов и градиентов.

    Если ваше приложение просто показывает закругленные цены на сайте, Math.sumPrecise() может быть не критичен. Но если вы работаете с реальными деньгами, измерениями или сложными вычислениями - это инструмент, который стоит иметь под рукой.

    Практические примеры и скорость

    Давайте посмотрим на более реальный сценарий. Предположим, у вас есть массив с результатами платежей:

    const payments = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7];
    
    // Старый способ
    const oldSum = payments.reduce((a, b) => a + b, 0);
    console.log(oldSum); // 2.799999999999999
    
    // Новый способ
    const newSum = Math.sumPrecise(payments);
    console.log(newSum); // 2.8
    

    Разница не всегда видна сразу, но при большом количестве чисел или при специфических комбинациях ошибки накапливаются. Math.sumPrecise() использует алгоритм, который отслеживает и компенсирует эти ошибки.

    Что касается производительности - да, Math.sumPrecise() работает медленнее, чем простое суммирование в цикле. Это необходимая цена за точность. По этой причине метод назван именно sumPrecise, а не просто sum - чтобы разработчик сознательно выбирал между скоростью и точностью. Если вам нужна максимальная производительность и точность не критична, используйте обычное суммирование. Если точность важнее - вот вам Math.sumPrecise().

    Что нужно знать о совместимости

    Сегодня, в марте 2026 года, вы не можете полагаться на Math.sumPrecise() во всех браузерах. Firefox и Safari уже поддерживают эту фичу, но Chrome, Edge и мобильные браузеры еще нет. Если вы пишете код, который должен работать везде, есть несколько подходов:

    • Используйте полифилл: Существуют библиотеки, которые реализуют точное суммирование на JavaScript. Например, xsum - MIT-лицензированная библиотека, которая делает ровно это. Она специально разработана для избежания проблем с пользовательским кодом.
    • Проверяйте наличие функции: Пишите код так, чтобы он работал с Math.sumPrecise(), если она доступна, и используйте fallback, если нет.
    • Ждите всеобщей поддержки: Если ваш проект все еще находится в планах, можете отложить внедрение на потом.
    function sumNumbers(numbers) {
      if (Math.sumPrecise) {
        return Math.sumPrecise(numbers);
      } else {
        return numbers.reduce((a, b) => a + b, 0);
      }
    }
    

    Это простой вариант обертки, который обеспечит fallback-поведение.

    О названии и философия API

    По-английски функция названа Math.sumPrecise(), а не просто Math.sum(). Это выбор был сделан сознательно. На первый взгляд, Math.sum() выглядит более естественно и коротко. Но суть в том, чтобы разработчик понимал - эта функция работает по другому алгоритму, чем наивное суммирование.

    Есть еще несколько интересных решений, которые приняли авторы предложения:

    • Отказ от преобразования типов: В отличие от Math.max() и Math.min(), которые пытаются преобразовать аргументы в числа, sumPrecise() бросает ошибку при нечисловых значениях. Это делает поведение более предсказуемым и помогает поймать ошибки на ранней стадии.
    • Возврат -0 для пустого массива: Это математически корректно и гарантирует определенные свойства функции. Например, что сумма пустого массива плюс сумма другого массива равна сумме того же другого массива.
    • Отсутствие поддержки BigInt: Было решено, что смешивание Number и BigInt в одной функции создало бы больше проблем, чем пользы. Лучше иметь отдельную функцию для BigInt или обрабатывать их отдельно.

    Перспективы развития и ожидания

    С тем, как браузеры постепенно добавляют поддержку Math.sumPrecise(), можно ожидать роста его использования. Особенно там, где точность важна - в финтехе, науке и разработке сложных приложений. Сообщество JavaScript давно ждало встроенного решения для этой проблемы.

    Пока что эта фича находится в процессе внедрения, но есть четкий список браузеров, которые уже поддерживают или будут поддерживать ее в ближайшее время. Это означает, что новые проекты смогут рассчитывать на эту функцию, а старые могут постепенно переходить на нее по мере расширения поддержки. Главное - не забывать о fallback-вариантах для пользователей, у которых установлены более старые версии браузеров.

    1 ответ Последний ответ
    0

    Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.

    Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.

    С вашими комментариями этот пост мог бы стать ещё лучше 💗

    Зарегистрироваться Войти

    Категории

    • Главная
    • Новости
    • Фронтенд
    • Бекенд
    • Языки программирования

    Контакты

    • Сотрудничество
    • info@exlends.com

    © 2024 - 2026 ExLends, Inc. Все права защищены.

    Политика конфиденциальности
    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Войдите или зарегистрируйтесь для поиска.
    • Первое сообщение
      Последнее сообщение
    0
    • Лента
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы