JavaScript: эффективная целочисленная арифметика

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

в частности, поведение переполнения должно соответствовать другим языкам: например, добавление одного в INT_MAX должно дайте INT_MIN. Целые числа должны быть 32-разрядными или 64-разрядными.

7 ответов


Я нашел эту реализацию BigIntegers в Javascript:http://www-cs-students.stanford.edu / ~tjw / jsbn/

возможно, это поможет?

Edit: кроме того, библиотека закрытия Google реализует 64-разрядные целые числа: http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/math/long.js

Они по существу просто генерируют объекты удобства, хотя и не будут ничего делать для улучшения фундаментального эффективность типа данных.


Итак, каков наиболее эффективный способ реализации целых чисел в JavaScript?

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

в частности, поведение переполнения должно соответствовать другим языкам: например, добавление одного в INT_MAX должно давать INT_MIN. Целые числа должны быть 32-разрядными или 64-битовый.

вы можете достичь семантики стандартной 32-разрядной целочисленной арифметики, отметив, что JavaScript преобразует "числа" в 32-разрядные целые числа для побитовых операций. >>> (unsigned right shift) преобразует свой операнд в 32-разрядное целое число без знака, а остальные (все остальные сдвиги и побитовые и/или) преобразуют свой операнд в 32-разрядное целое число со знаком. Например:

  • 0xFFFFFFFF | 0 доходность -1 (подпись литой)
  • (0xFFFFFFFF + 1) | 0 дает 0 (переполнение)
  • -1 >>> 0 доходность 0xFFFFFFFF (неподписанные литой)

на современном процессоре, если вы ограничиваете целочисленные значения диапазоном + - 2^52, используя double будет едва ли менее эффективным, чем использование long.

на double тип IEE754 имеет 53 бита мантиссы, поэтому вы можете легко представить 32-разрядный целочисленный диапазон, а затем некоторые.

в любом случае, остальная часть Javascript будет гораздо большим узким местом, чем отдельные инструкции CPU, используемые для обработки арифметики.


все числа являются числами. Ничего не поделаешь. JavaScript не имеет типа byte или int. Либо разберитесь с ограничениями, либо используйте язык более низкого уровня для записи компилятора.

единственный разумный вариант, если вы хотите достичь этого, - отредактировать один из интерпретаторов JavaScript (скажем, V8) и расширить JS, чтобы разрешить доступ к собственным байтам C.


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

... Если производительность и эффективность-ваша забота, придерживайтесь двойников.


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

Это, конечно, означает, что операции с плавающей запятой на вашем языке будут значительно быстрее, чем целочисленные операции, победив большую часть цели наличие типа integer в первую очередь.


обратите внимание, что ECMA-262 Edition 3 добавлен Число.прототип.toFixed, который принимает аргумент точности, говорящий, сколько цифры после десятичной запятой показывать. Используйте этот метод хорошо и вы не будет возражать против несоответствия между конечная точность базы 2 и "произвольная" или "соответствующая" точность база 10, которую мы используем каждый день. - Брендан Айх