JavaScript% (modulo) дает отрицательный результат для отрицательных чисел

Согласно Google Calculator (-13) % 64 есть 51.

В соответствии с Javascript (см. JSBin) -13.

Как это исправить?

Ответ 2

Использование Number.prototype является SLOW, потому что каждый раз, когда вы используете метод прототипа, ваш номер обернут в Object. Вместо этого:

Number.prototype.mod = function(n) {
  return ((this % n) + n) % n;
}

Использование:

function mod(n, m) {
  return ((n % m) + m) % m;
}

Смотрите: http://jsperf.com/negative-modulo/2

~ 97% быстрее, чем использование прототипа. Если для вас важна производительность, конечно.

Ответ 3

Оператор % в JavaScript - это оператор останова, а не оператор modulo (основное отличие заключается в том, как обрабатываются отрицательные числа):

-1 % 8 // -1, not 7

Ответ 4

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

var mod = function (n, m) {
    var remain = n % m;
    return Math.floor(remain >= 0 ? remain : remain + m);
};
mod(5,22)   // 5
mod(25,22)  // 3
mod(-1,22)  // 21
mod(-2,22)  // 20
mod(0,22)   // 0
mod(-1,22)  // 21
mod(-21,22) // 1

И, конечно,

mod(-13,64) // 51

Ответ 5

Принятый ответ заставляет меня немного нервничать, потому что он повторно использует оператора%. Что делать, если Javascript изменяет поведение в будущем?

Ниже приведено обходное решение, которое не использует повторно%:

function mod(a, n) {
    return a - (n * Math.floor(a/n));
}

mod(1,64); // 1
mod(63,64); // 63
mod(64,64); // 0
mod(65,64); // 1
mod(0,64); // 0
mod(-1,64); // 63
mod(-13,64); // 51
mod(-63,64); // 1
mod(-64,64); // 0
mod(-65,64); // 63

Ответ 6

Хотя он не ведет себя так, как вы ожидали, это не значит, что JavaScript не "ведет себя". Это выбор JavaScript, сделанный для его модульного вычисления. Потому что, по определению, любой ответ имеет смысл.

Смотрите этот из Википедии. Вы можете увидеть справа, как разные языки выбрали знак результата.

Ответ 7

Если x - целое число, а n - степень 2, вы можете использовать x & (n - 1) вместо x % n.

> -13 & (64 - 1)
51 

Ответ 8

Итак, кажется, что если вы пытаетесь модифицировать градусы (так что если у вас есть -50 градусов - 200 градусов), вы бы хотели использовать что-то вроде:

function modrad(m) {
    return ((((180+m) % 360) + 360) % 360)-180;
}

Ответ 9

Это не ошибка, есть 3 функции для вычисления по модулю, вы можете использовать ту, которая соответствует вашим потребностям (я бы рекомендовал использовать функцию Евклида)

Усечение функции десятичной части

console.log(  41 %  7 ); //  6
console.log( -41 %  7 ); // -6
console.log( -41 % -7 ); // -6
console.log(  41 % -7 ); //  6

Функция целочисленной части

Number.prototype.mod = function(n) {
    return ((this%n)+n)%n;
};

console.log( parseInt( 41).mod( 7) ); //  6
console.log( parseInt(-41).mod( 7) ); //  1
console.log( parseInt(-41).mod(-7) ); // -6
console.log( parseInt( 41).mod(-7) ); // -1

Евклидова функция

Number.prototype.mod = function(n) {
    var m = ((this%n)+n)%n;
    return m < 0 ? m + Math.abs(n) : m;
};

console.log( parseInt( 41).mod( 7) ); // 6
console.log( parseInt(-41).mod( 7) ); // 1
console.log( parseInt(-41).mod(-7) ); // 1
console.log( parseInt( 41).mod(-7) ); // 6

Ответ 10

Я имею дело с неграмотными а и отрицательными n тоже

 //best perf, hard to read
   function modul3(a,n){
        r = a/n | 0 ;
        if(a < 0){ 
            r += n < 0 ? 1 : -1
        }
        return a - n * r 
    }
    // shorter code
    function modul(a,n){
        return  a%n + (a < 0 && Math.abs(n)); 
    }

    //beetween perf and small code
    function modul(a,n){
        return a - n * Math[n > 0 ? 'floor' : 'ceil'](a/n); 
    }

Ответ 11

Существует пакет NPM, который будет работать для вас. Вы можете установить его с помощью следующей команды.

npm install just-modulo --save

Использование, скопированное из README

import modulo from 'just-modulo';

modulo(7, 5); // 2
modulo(17, 23); // 17
modulo(16.2, 3.8); // 17
modulo(5.8, 3.4); //2.4
modulo(4, 0); // 4
modulo(-7, 5); // 3
modulo(-2, 15); // 13
modulo(-5.8, 3.4); // 1
modulo(12, -1); // NaN
modulo(-3, -8); // NaN
modulo(12, 'apple'); // NaN
modulo('bee', 9); // NaN
modulo(null, undefined); // NaN

Репозиторий GitHub можно найти по следующей ссылке:

https://github.com/angus-c/just/tree/master/packages/number-modulo