Ответы:
Для некоторого числа y
и некоторого делителя x
вычислить частное ( quotient
) и остаток ( remainder
) как:
var quotient = Math.floor(y/x);
var remainder = y % x;
floor
и %
вместе не согласовано таким образом. Либо используйте trunc
вместо floor
(тем самым разрешая отрицательные остатки), либо используйте вычитание, чтобы получить остаток ( rem = y - div * x
).
rem
любом случае, вы можете получить частное div
быстрее без пола: (y - rem) / x
. 2. Кстати, операция по модулю в соответствии с рекомендуемым определением Дональда Кнута (знак-совпадение-делитель, а не остаток, то есть евклидов модуль, или знак-совпадение-дивиденд JavaScript) - это то, что мы можем кодировать в JavaScript как function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.
Я не эксперт в побитовых операторах, но вот еще один способ получить целое число:
var num = ~~(a / b);
Это будет работать правильно и для отрицательных чисел, а также Math.floor()
будет округлено в неправильном направлении.
Это также кажется правильным:
var num = (a / b) >> 0;
a/b | 0
~~int
, int | 0
и int >> 0
не изменяет начальный аргумент, но заставляет интерпретатор передавать неотъемлемую часть оператору.
floor
вряд ли поворачивает в неправильном направлении, учитывая его имя - просто не то направление, которое люди обычно хотят, хотя!
a = 12447132275286670000; b = 128
Math.floor(a/b)
-> 97243220900677100
и ~~(a/b)
-> -1231452688
.
~~(5/2) --> 2
как делает (5/2)>>0 --> 2
, но ~~(5/2) + 1 --> 3
пока ~~(5/2)>>0 + 1 --> 1
. ~~
это хороший выбор, потому что приоритет более уместен.
Я сделал несколько тестов скорости на Firefox.
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
Вышеуказанное основано на 10 миллионах испытаний для каждого.
Вывод: используйте (a/b>>0)
(или (~~(a/b))
или (a/b|0)
), чтобы добиться повышения эффективности примерно на 20%. Также имейте в виду, что все они несовместимы с Math.floor
, когда a/b<0 && a%b!=0
.
Math.floor
других функциях API «кто знает, сколько» или узнать об ~
операторе (побитовом нет) и о том, как побитовые операции работают в JS, а затем понять эффект двойной тильды?
Math.floor
лучше. И даже если нет, то этот является Googleable.
ES6 представляет новый Math.trunc
метод. Это позволяет исправить ответ @ MarkElliot, чтобы он работал и для отрицательных чисел:
var div = Math.trunc(y/x);
var rem = y % x;
Обратите внимание, что Math
методы имеют преимущество перед побитовыми операторами в том, что они работают с числами свыше 2 31 .
18014398509481984 == 18014398509481985
.
~~(x/y)
. Нужно поддерживать большие числа до 54 битов со знаком? Используйте, Math.trunc
если у вас есть, или Math.floor
иным образом (исправить для отрицательных чисел). Нужно поддерживать еще большие цифры? Используйте некоторую библиотеку больших чисел.
divmod
, вы можете реализовать это так:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
var remainder = x % y;
return (x - remainder) / y;
Math.trunc
:). Я проверил с 100,3; -100,3; 100, -3 и -100, -3. Конечно, прошло много времени с тех пор, как ваш комментарий изменился.
Я обычно использую:
const quotient = (a - a % b) / b;
const remainder = a % b;
Это, вероятно, не самый элегантный, но это работает.
Вы можете использовать функцию, parseInt
чтобы получить усеченный результат.
parseInt(a/b)
Чтобы получить остаток, используйте оператор мод:
a%b
У parseInt есть некоторые подводные камни со строками, чтобы избежать использования параметра radix с основанием 10
parseInt("09", 10)
В некоторых случаях строковое представление числа может быть научной нотацией, в этом случае parseInt даст неправильный результат.
parseInt(100000000000000000000000000000000, 10) // 1e+32
Этот вызов даст 1 как результат.
parseInt
следует избегать, когда это возможно. Вот предупреждение Дугласа Крокфорда: «Если первый символ строки равен 0, то строка оценивается в базе 8 вместо базы 10. В базе 8, 8 и 9 не являются цифрами, поэтому parseInt (" 08 ") и parseInt ("09") в качестве результата выдаются 0. Эта ошибка вызывает проблемы в программах, которые анализируют даты и время. К счастью, parseInt может принимать параметр radix, так что parseInt ("08", 10) выдает 8. Я рекомендую вам всегда предоставить параметр radix. " archive.oreilly.com/pub/a/javascript/excerpts/...
parseInt
следует избегать; Просто есть некоторые ошибки, о которых нужно знать. Вы должны знать об этих вещах и быть готовыми справиться.
parseInt
с аргументом числа. parseInt
должен анализировать частично-числовые строки, а не усекать числа.
JavaScript вычисляет прямо пол отрицательных чисел и остаток нецелых чисел, следуя математическим определениям для них.
FLOOR определяется как «наибольшее целое число, меньшее, чем параметр», таким образом:
REMAINDER определяется как «остаток» от деления (евклидова арифметика). Когда дивиденд не является целым числом, частное, как правило, также не является целым числом, то есть нет остатка, но если частное вынуждено быть целым числом (и это то, что происходит, когда кто-то пытается получить остаток или модуль число с плавающей запятой), очевидно, будет нецелое «оставшееся».
JavaScript действительно рассчитывает все, как и ожидалось, поэтому программист должен быть осторожным, чтобы задавать правильные вопросы (и люди должны быть осторожны, чтобы ответить на то, что спрашивают!) Первый вопрос Ярина был НЕ «что такое целочисленное деление X на Y», но, вместо этого, «ВЕСЬ количество раз, когда данное целое число ПРОХОДИТ В другое». Для положительных чисел ответ одинаков для обоих, но не для отрицательных, потому что целочисленное деление (делитель на делитель) будет на -1 меньше, чем число, которое (делитель) «переходит» в другое (делимое). Другими словами, FLOOR вернет правильный ответ для целочисленного деления отрицательного числа, но Ярин этого не спрашивал!
gammax правильно ответил, что код работает так, как спросил Ярин. С другой стороны, Самуил не прав, он, наверное, не делал математику, иначе он бы увидел, что это работает (также он не сказал, что было делителем его примера, но я надеюсь, что это было 3):
Остаток = X% Y = -100% 3 = -1
GoesInto = (X - остаток) / Y = (-100 - -1) / 3 = -99 / 3 = -33
Кстати, я протестировал код на Firefox 27.0.1, он работал как положено, с положительными и отрицательными числами, а также с нецелыми значениями, как для делимого, так и для делителя. Пример:
-100,34 / 3,57: GoesInto = -28, остаток = -0,3800000000000079
Да, я заметил, что здесь есть проблема точности, но у меня не было времени проверить ее (я не знаю, проблема ли это с Firefox, Windows 7 или с FPU моего процессора). Для вопроса Ярина, который включает только целые числа, код gammax работает отлично.
Вычисление количества страниц может быть сделано за один шаг: Math.ceil (x / y)
Комментарий Алекса Мура-Ниеми как ответ:
Для Rubyists здесь от Google в поисках divmod
, вы можете реализовать это так:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Результат:
// [2, 33]
divmod
использует floored Division ( Math.floor
), который отличается от усеченного Division ( Math.trunc
), когда задействованы отрицательные числа. Это относится и к пакету NPMdivmod
, Rubydivmod
, SWI-Prologdivmod
и, возможно, ко многим другим реализациям.
divmod
существует, потому что он выполняет в два раза быстрее, чем вычисление двух операций по отдельности. Предоставление такой функции без этого выигрыша в производительности может сбить с толку.
Если вы просто делитесь со степенью двойки, вы можете использовать побитовые операторы:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(Первое является частным, второе - оставшимся)
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
.
Вы можете использовать троичный, чтобы решить, как обрабатывать положительные и отрицательные целочисленные значения.
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
Если число положительное, все в порядке. Если число отрицательное, оно добавит 1 из-за того, как Math.floor обрабатывает отрицания.
Это всегда будет обрезаться до нуля. Не уверен, что уже слишком поздно, но вот оно:
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
Если вам нужно вычислить остаток для очень больших целых чисел, которые среда выполнения JS не может представить как таковая (любое целое число больше 2 ^ 32 представляется как число с плавающей точкой, и поэтому оно теряет точность), вам нужно сделать некоторый трюк.
Это особенно важно для проверки большого количества контрольных цифр, которые присутствуют во многих случаях нашей повседневной жизни (номера банковских счетов, кредитные карты, ...)
Прежде всего, вам нужен ваш номер в виде строки (иначе вы уже потеряли точность, а остальное не имеет смысла).
str = '123456789123456789123456789'
Теперь вам нужно разбить вашу строку на более мелкие части, достаточно маленькие, чтобы объединение любого остатка и фрагмента строки могло уместиться в 9 цифр.
digits = 9 - String(divisor).length
Подготовьте регулярное выражение для разбиения строки
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
Например, если digits
7, регулярное выражение
/.{1,7}(?=(.{7})+$)/g
Он соответствует непустой подстроке максимальной длины 7, за которой следует ( (?=...)
является положительным взглядом) количество символов, кратное 7. «g» - заставить выражение проходить по всей строке, не останавливаясь при первом совпадении.
Теперь преобразуйте каждую часть в целое число и вычислите остатки reduce
(добавив обратно предыдущий остаток - или 0 - умноженный на правильную степень 10):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
Это будет работать из-за алгоритма остатка «вычитания»:
n mod d = (n - kd) mod d
который позволяет заменить любую «начальную часть» десятичного представления числа его остатком, не затрагивая последний остаток.
Окончательный код будет выглядеть так:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
3.5 % 2
оценивается в 1,5. Обязательно обрабатывайте (parseInt, floor и т. Д.) Как требуется