Вычитание длинных чисел в javascript

почему q == 0 в следующем скрипте?

<script>
  var start = 1234567890123456789;
  var end =   1234567890123456799;
  var q = end - start;
  alert(q);
</script>

Я думаю, что результат должен быть 10. Как правильно вычесть эти два числа?

4 ответов


потому что числа в JavaScript имеют плавающую точку. Они имеют ограниченную точность.

когда JavaScript видит очень длинное число, он округляет его до ближайшего числа, которое он может представлять как 64-битный float. В вашем сценарии,start и end округляется до того же значения.

alert(1234567890123456789);   // says: 1234567890123456800
alert(1234567890123456799);   // says: 1234567890123456800

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


Джейсон уже написал почему. Для решения вы можете получить библиотеку Javascript BigInt по адресуhttp://www-cs-students.stanford.edu / ~tjw / jsbn/


const subtract = (a, b) => [a, b].map(n => [...n].reverse()).reduce((a, b) => a.reduce((r, d, i) => {
    let s = d - (b[i] || 0)
    if (s < 0) {
        s += 10
        a[i + 1]--
    }
    return '' + s + r
}, '').replace(/^0+/, ''))


лучше использовать библиотеку big-integer для этих вещей, чтобы обрабатывать все различные тестовые случаи.

Это только для общего случая, вы можете использовать....


это объясняется в документация JavaScript:

согласно стандарту ECMAScript, существует только один тип чисел:двойной точности 64-разрядный двоичный формат IEEE 754 значение (номера между -(253-1) и 253-1). для целых чисел нет определенного типа.

страница Википедии о двойной точности формат с плавающей запятой объясняю:

между 252= 4,503,599,627,370,496 и 253= 9,007,199,254,740,992 числа представимы абсолютно целые. Для следующего диапазона, от 253 to 254, все умножается на 2, поэтому представимые числа являются четными и т. д.

(все целые числа меньше 252 представлены точно.)

1234567890123456789 и 1234567890123456799 больше, чем 260= 1152921504606846976. При этой величине только около 1% целых чисел хранятся точно с использованием формата с плавающей запятой двойной точности.

эти два не могут быть сохранены точно. Они оба округлены до 1234567890123456800.


на документация JavaScript также объясняет, как сказать, если целое число хранится точно:

[...] и начиная с ECMAScript 6, вы также можете проверить, находится ли число в диапазоне чисел с плавающей запятой двойной точности, используя Number.isSafeInteger() а также Number.MAX_SAFE_INTEGER и Number.MIN_SAFE_INTEGER. За пределами этого диапазона целые числа в JavaScript больше не безопасны и будут аппроксимацией значения с плавающей запятой двойной точности.