Согласно Google Calculator (-13) % 64
есть 51
.
В соответствии с Javascript (см. JSBin) -13
.
Как это исправить?
Согласно Google Calculator (-13) % 64
есть 51
.
В соответствии с Javascript (см. JSBin) -13
.
Как это исправить?
Number.prototype.mod = function(n) {
return ((this%n)+n)%n;
};
Взято из этой статьи: Ошибка модуля JavaScript
Использование 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% быстрее, чем использование прототипа. Если для вас важна производительность, конечно.
Оператор %
в JavaScript - это оператор останова, а не оператор modulo (основное отличие заключается в том, как обрабатываются отрицательные числа):
-1 % 8 // -1, not 7
В любом случае вот учебник с функцией "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
Принятый ответ заставляет меня немного нервничать, потому что он повторно использует оператора%. Что делать, если 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
Хотя он не ведет себя так, как вы ожидали, это не значит, что JavaScript не "ведет себя". Это выбор JavaScript, сделанный для его модульного вычисления. Потому что, по определению, любой ответ имеет смысл.
Смотрите этот из Википедии. Вы можете увидеть справа, как разные языки выбрали знак результата.
Если x
- целое число, а n
- степень 2, вы можете использовать x & (n - 1)
вместо x % n
.
> -13 & (64 - 1)
51
Итак, кажется, что если вы пытаетесь модифицировать градусы (так что если у вас есть -50 градусов - 200 градусов), вы бы хотели использовать что-то вроде:
function modrad(m) {
return ((((180+m) % 360) + 360) % 360)-180;
}
Это не ошибка, есть 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
Я имею дело с неграмотными а и отрицательными 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);
}
Существует пакет 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