Целочисленное деление с остатком в JavaScript?

в JavaScript, как мне получить:

  1. целое число раз заданное целое число переходит в другое?
  2. остаток?

15 ответов


для некоторого числа y и какой делитель x вычислить коэффициент (quotient) и остаток (remainder) как:

var quotient = Math.floor(y/x);
var remainder = y % x;

Я не эксперт в побитовых операторах, но вот еще один способ получить целое число:

var num = ~~(a / b);

Это будет работать для отрицательных чисел, а Math.floor() будет вращаться в неправильном направлении.

это тоже кажется правильным:

var num = (a / b) >> 0;

Я сделал несколько тестов скорости на 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.


ЕС6 вводит новый Math.trunc метод. Это позволяет исправить @MarkElliot это чтобы он работал и для отрицательных чисел:

var div = Math.trunc(y/x);
var rem = y % x;

отметим, что Math методы имеют преимущество перед побитовыми операторами, что они работают с числами более 231.


var remainder = x % y;
return (x - remainder) / y;

вы можете использовать функцию parseInt чтобы получить усеченный результат.

parseInt(a/b)

чтобы получить остаток, используйте Mod operator:

a%b

parseInt имеют некоторые подводные камни со строками, чтобы избежать использования параметра radix с базой 10

parseInt("09", 10)

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

parseInt(100000000000000000000000000000000, 10) // 1e+32

этот вызов приведет к 1 в результате.


JavaScript вычисляет справа пол отрицательных чисел и остаток нецелых чисел, следуя математическим определениям для них.

FLOOR определяется как "наибольшее целое число, меньшее параметра", таким образом:

  • положительные числа: FLOOR (X)=целая часть X;
  • отрицательные числа: FLOOR (X)=целая часть X минус 1 (потому что она должна быть меньше параметра, т. е. больше отрицательно!)

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

JavaScript вычисляет все, как ожидалось, поэтому программист должен быть осторожен, чтобы задавать правильные вопросы (и люди должны быть осторожны, чтобы ответить на то, что спрашивают!) Первым вопросом Ярина было не "что такое целочисленное деление X на Y", а"целое число раз, когда данное целое число переходит в другое". Для положительных чисел ответ одинаков для обоих, но не для отрицательных чисел, потому что целочисленное деление (дивиденд по делителю) будет -1 меньше, чем раз, когда число (делитель) "переходит в" другое (дивиденд). В других слова, ПОЛ вернет правильный ответ для целочисленного деления отрицательного числа, но Ярин этого не спрашивал!

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.floor(operation) возвращает округленное вниз значение операции.

Пример 1st вопрос:

var x = 5;
var y = 10.4;
var z = Math.floor(x + y);

console.log(z);

Алекс Мур-Ниемикомментарий в качестве ответа:

для рубистов здесь из Google в поисках divmod, вы можете реализовать это так:

function divmod(x, y) {
  var div = Math.trunc(x/y);
  var rem = x % y;
  return [div, rem];
}

результат:

// [2, 33]

Если вы просто делите с степенями два, вы можете использовать побитовые операторы:

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];
}

(первый фактор, второй остаток)


вычисление количества страниц может быть сделано за один шаг: Математика.ceil (x/y)


вы можете использовать троичный, чтобы решить, как обрабатывать положительные и отрицательные целочисленные значения.

var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1

если число положительное, все в порядке. Если число отрицательное, оно добавит 1 из-за, как математика.пол обрабатывает негативы.


Я обычно использую (a - a % b) / b. Возможно, он не самый элегантный, но он работает.


это всегда будет сокращаться до нуля. Не уверен, что уже слишком поздно, но вот оно:

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 представлено как float и поэтому теряет точность), вам нужно сделать какой-то трюк.

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

прежде всего вам нужен ваш номер в виде строки (в противном случае вы уже потеряли точность, а остальное не имеет смысла).

str = '123456789123456789123456789'

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

digits = 9 - String(divisor).length

подготовьте регулярное выражение для разделения строки

splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')

например, если digits равно 7, регулярное выражение

/.{1,7}(?=(.{7})+$)/g

он соответствует непустой подстроке максимальной длины 7, за которой следует ((?=...) является положительным lookahead) на несколько символов, кратных 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);
}