JavaScript % (modulo) 给出负数的负结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4467539/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 12:32:54  来源:igfitidea点击:

JavaScript % (modulo) gives a negative result for negative numbers

javascriptmathmodulo

提问by Alec Gorge

According to Google Calculator(-13) % 64is 51.

根据谷歌计算器(-13) % 6451.

According to Javascript (see this JSBin) it is -13.

根据 Javascript(请参阅此JSBin),它是-13.

How do I fix this?

我该如何解决?

回答by Enrique

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

Taken from this article: The JavaScript Modulo Bug

摘自这篇文章:JavaScript Modulo Bug

回答by StuR

Using Number.prototypeis SLOW, because each time you use the prototype method your number is wrapped in an Object. Instead of this:

使用Number.prototype很慢,因为每次使用原型方法时,您的数字都会被包裹在Object. 取而代之的是:

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

Use:

用:

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

See: http://jsperf.com/negative-modulo/2

见:http: //jsperf.com/negative-modulo/2

~97% faster than using prototype. If performance is of importance to you of course..

比使用原型快 97%。如果性能对你来说当然很重要..

回答by Rob Sobers

The %operator in JavaScript is the remainder operator, not the modulo operator (the main difference being in how negative numbers are treated):

%JavaScript中运算符是求余运算符,而不是模运算符(如何负数的处理方式主要区别):

-1 % 8 // -1, not 7

-1 % 8 // -1, not 7

回答by Shanimal

A "mod" function to return a positive result.

返回正结果的“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

And of course

而且当然

mod(-13,64) // 51

回答by wisbucky

The accepted answer makes me a little nervous because it re-uses the % operator. What if Javascript changes the behavior in the future?

接受的答案让我有点紧张,因为它重新使用了 % 运算符。如果 Javascript 将来改变行为怎么办?

Here is a workaround that does not re-use %:

这是一个不重复使用 % 的解决方法:

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

回答by dheerosaur

Though it isn't behaving as you expected, it doesn't mean that JavaScript is not 'behaving'. It is a choice JavaScript made for its modulo calculation. Because, by definition either answer makes sense.

尽管它的行为不像您预期​​的那样,但这并不意味着 JavaScript 没有“行为”。这是 JavaScript 为其模计算所做的选择。因为,根据定义,任何一个答案都有意义。

See thisfrom Wikipedia. You can see on the right how different languages chose the result's sign.

从维基百科看到这个。您可以在右侧看到不同的语言如何选择结果的符号。

回答by quasimodo

If xis an integer and nis a power of 2, you can use x & (n - 1)instead of x % n.

如果x是整数并且n是 2 的幂,则可以使用x & (n - 1)代替x % n

> -13 & (64 - 1)
51 

回答by JayCrossler

So it seems that if you're trying to mod around degrees (so that if you have -50 degrees - 200 degrees), you'd want to use something like:

因此,似乎如果您尝试修改度数(因此如果您有 -50 度 - 200 度),您可能想要使用以下内容:

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

回答by zessx

This is not a bug, there's 3 functions to calculate modulo, you can use the one which fit your needs (I would recommend to use Euclidean function)

这不是错误,有 3 个函数可以计算模数,您可以使用适合您需要的函数(我建议使用欧几里得函数)

Truncating the decimal part function

截断小数部分函数

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

Integer part function

整数部分函数

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

Euclidean function

欧氏函数

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

回答by bormat

I deal with négative a and negative n too

我也处理负 a 和负 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); 
    }