Разница вычислений Int32 между Java и JavaScript

Мне нужно переписать устаревший код Java, выполняющий арифметические преобразования из Java в TypeScript/JavaScript. Проблема в том, что устаревший код использует тип int Java (32-битный со знаком) и полагается на переполнения. Я почти получил то, что хотел, используя Int32Array в JavaScript, но у меня все еще есть разница, которую я не могу объяснить. Смотри ниже.

Джава:

int current = -1599751945;
int next = current * 0x08088405 + 1;
System.out.println("next = " + next);

Вывод: следующий = 374601940

Javascript:

const a = new Int32Array(4)

a[0] = -1599751945
a[1] = 0x08088405
a[2] = 1
a[3] = a[0]*a[1] + a[2]

console.info('a[3] = ' + a[3])

Выход: а[3] = 374601952

Может кто-нибудь объяснить разницу? И как я могу получить такой же результат в JavaScript? Я пробовал операции сдвига, принуждение с помощью | 0, методы преобразования и т. д., Но лучший результат - тот, что выше.

Связанный вопрос, который может помочь: stackoverflow.com/q/30678303/5133585

Sweeper 10.02.2023 10:53
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
1
88
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я не могу дать окончательный ответ, почему именно вы получаете эти точные цифры; но учтите, что все числа в JS являются двойными.

Итак, в то время как current * 0x08088405 выполняется с использованием целочисленной арифметики в Java, a[0]*a[1] выполняется с использованием двойной арифметики в JS, поэтому эти промежуточные результаты отличаются; и ограниченная точность двойного числа означает, что добавление 1 к этому фактически не меняет значение:

console.info(a[0]*a[1]) => -215607868985706270
console.info(a[0]*a[1] + a[2]) => = -215607868985706270

Сравните это с Java, где используется целочисленная арифметика:

int[] a = { -1599751945, 0x08088405, 1};
System.out.println(a[0]*a[1])          => 374601939
System.out.println(a[0]*a[1] + a[2])   => 374601940

Если мы заставим Java делать это в двойной арифметике:

double[] a = { -1599751945, 0x08088405, 1};
System.out.println(a[0]*a[1]);         => -2.15607868985706272E17
System.out.println(a[0]*a[1] + a[2]);  => -2.15607868985706272E17

Вы можете видеть, что это почти то же самое, но отличается младшей значащей цифрой:

-215607868985706270  // JS
-215607868985706272  // Java

Я не знаю, почему здесь такая разница.

Спасибо за подробное объяснение!

airone 10.02.2023 11:45

Числа с плавающей запятой поддерживают точность только до определенного количества цифр. JavaScript преобразует числа больше 32 бит в числа с плавающей запятой.

Java здесь "более правильный".

// -215607868985706285 is the 64 bit result of your multiplication
console.info(-215607868985706285); // will print -215607868985706285

См. Не работает ли математика с плавающей запятой? для общего обсуждения этой темы.

Ответ принят как подходящий

Используйте Math.imul() в JavaScript. Это должно дать правильный результат.

const a = new Int32Array(4)

a[0] = -1599751945
a[1] = 0x08088405
a[2] = 1
a[3] = Math.imul(a[0], a[1]) + a[2]

console.info('a[3] = ' + a[3])

Дополнительную информацию о том, почему можно найти здесь.

Другие вопросы по теме