Вычитание длинных чисел в JavaScript - PullRequest
9 голосов
/ 12 января 2010

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

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

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

Ответы [ 4 ]

20 голосов
/ 12 января 2010

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

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

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

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

.
3 голосов
/ 12 января 2010

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

2 голосов
/ 17 июля 2018

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+/, ''))


Лучше использовать для этих целей большую целочисленную библиотеку, чтобы обрабатывать все разные тестовые случаи.

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

0 голосов
/ 20 января 2018

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

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

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

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

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

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

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


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

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

...