整数除以JavaScript中的余数?

Yar*_*rin 854 javascript math modulo integer-division

在JavaScript中,我如何获得:

  1. 给定整数进入另一个整数的整数倍?
  2. 剩下的?

Mar*_*iot 1137

对于某些数字y和一些除数,x将quotient(quotient)和remainder(remainder)计算为:

var quotient = Math.floor(y/x);
var remainder = y % x;
Run Code Online (Sandbox Code Playgroud)

  • %适用于JavaScript中的浮点数(这与许多其他语言不同),这可能不是所希望的:`3.5%2`的计算结果为1.5.确保根据需要处理(parseInt,floor等) (77认同)
  • 数学中-4.5的整数部分是-5,因为-5是"最高可能的整数仍然低于-4.5". (15认同)
  • 但是,无论你决定对负数做什么,它应该在商和余数之间保持一致.同时使用`floor`和`%`并不一致.要么使用`trunc`而不是`floor`(从而允许负余数),要么使用减法来得到余数(`rem = y - div*x`). (5认同)
  • 1.如果你要计算剩余的`rem`,你可以更快地得到商`div`而不用地板:`(y - rem)/ x`.顺便说一下,Donald Knuth建议的模数运算(符号匹配 - 除数,而不是余数,即欧几里德模数,也不是JavaScript符号匹配 - 被除数),我们可以在JavaScript中将其编码为`function mod(a, n){return a%n +(Math.sign(a)!== Math.sign(n)?n:0); }`. (5认同)
  • -9 / 2 = -4.5。然后你取-4.5的地板,也就是-5。请记住,-5 小于 -4.5,并且地板运算被定义为小于给定值的最大整数。 (2认同)

use*_*716 350

我不是按位运算符的专家,但这是获得整数的另一种方法:

var num = ~~(a / b);
Run Code Online (Sandbox Code Playgroud)

这也适用于负数,而Math.floor()在错误的方向上.

这似乎也是正确的:

var num = (a / b) >> 0;
Run Code Online (Sandbox Code Playgroud)

  • 另一个人,其目的只是花了最后20分钟试图找出,显然是'a/b | 0` (80认同)
  • @ user113716 @BlueRaja Bitwise操作仅对整数类型有意义,JS(当然)知道这一点.`~~ int`,`int | 0`和`int >> 0`不修改初始参数,但使解释器将整数部分传递给运算符. (17认同)
  • 这是一个buu buu.`a = 12447132275286670000; b = 128``Math.floor(a/b)` - >`97243220900677100`和`~~(a/b)` - >`-1231452688`. (17认同)
  • 鉴于它的名字,`floor`在错误的方向上几乎没有 - 尽管不是人们通常想要的方向! (13认同)
  • 小心优先级.`~~(5/2) - > 2`和`(5/2)>> 0 - > 2`,但是`~~(5/2)+ 1 - > 3`,而`〜 〜(5/2)>> 0 + 1 - > 1`.`~~`是个不错的选择,因为优先级更合适. (7认同)
  • 只是为了澄清 - 这些实际上是有效的,因为它们是无操作,并且所有js按位运算都转换为32位整数 (5认同)
  • @ bfred.it Idk.第一次看到它们时,三元看起来很奇怪.[Null conditionals](http://stackoverflow.com/a/28352116/1028230)起初看起来也很奇怪.没有人说不要使用它们,因为它们看起来很聪明; 相反,他们是新的lang补充*,开发人员应该学习*.如果`~~`或`| 0`没有帮助存在,有人可能会想要添加它们.正如[Joel所说](https://www.joelonsoftware.com/2000/11/20/netscape-goes-bonkers/),"旧代码不生锈".不要仅仅因为它们已经陈旧而使用有用的现有约定.这个不错. (4认同)
  • 万一有人想知道哪个是最快的:http://jsperf.com/integer-division-math-floor-ab-vs-ab(Spoiler结果看起来没有结果). (3认同)
  • 同意Jonny Leeds.事实上,虽然这个解决方案值得一提,但我会拒绝它作为最佳编码实践.Mark Elliot的答案使用了为此目的提供的功能.这个答案依赖于按位操作的实现既不保证也不打算的行为. (2认同)
  • 答案是buubuus ~~(2147483648/1)= -2147483648(2147483648/1)>> 0 = -2147483648 (2认同)
  • 这基本上是代码混淆.不要这样聪明,使用稍长但更易读的`Math.floor`或ES6的新的Math.trunc(Edge 12+) (2认同)
  • @ bfred.it大多数开发人员已经接受使用`| 0`截断,特别是由于它在asm.js中的使用,所以你不能确切地说它混淆了代码,因为它的含义已经广为人知. (2认同)

Kal*_*lEl 192

我在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
Run Code Online (Sandbox Code Playgroud)

以上是基于每个1000万次试验.

结论:使用(a/b>>0)(或(~~(a/b))(a/b|0))可以使效率提高约20%.也请记住,他们都是不一致Math.floor的时候a/b<0 && a%b!=0.

  • 请注意,优化整数除法以获得速度只有在你*做很多*时才有意义.在任何其他情况下,我建议选择最简单的(对你和你的同事来说最简单). (35认同)
  • 好吧,如果你的同事不是用汇编程序编写芯片,他们可能会更好地理解`Math.floor`.即使不是,这个是可谷歌的. (8认同)
  • @ m01完全同意 - 对网上这样的东西太过关注了 (5认同)
  • 这是一组很好的测试用例:http://jsperf.com/whole-integer-division (4认同)
  • 这是整数除法方法的性能比较,而不是问题的答案。 (3认同)
  • 我发现 Math.floor() 的性能比其他人更稳定。上下起伏较小 (2认同)
  • @ m01但是哪个更难:学习`Math.floor`和谁知道多少其他API函数,或者学习`~`(按位非)运算符以及按位运算如何在JS中运行然后*理解*双波浪的效果? (2认同)
  • @JonnyLeeds 我来这里是为了寻找 Javascript 中的整数除法,这不是一个小众要求。 (2认同)
  • @MarkGreen是的,但是只是想这样做并不意味着您应该以怪异的形式编写它,只是因为它碰巧是最快的,没有充分的理由-通常,代码清晰通常是您的首要考虑。同样,这些测试在更改语言之后以及在不同的浏览器中可能完全没有意义-无论如何,您都需要进行分析以找出应用程序运行缓慢的原因。除非您已经优化了其他任何事物,否则不太可能成为整数除法! (2认同)

Ori*_*iol 125

ES6引入了新Math.trunc方法.这允许修复@MarkElliot的答案,使其也适用于负数:

var div = Math.trunc(y/x);
var rem = y % x;
Run Code Online (Sandbox Code Playgroud)

请注意,Math与按位运算符相比,这些方法具有优势,它们可以使用超过2 31的数字.

  • @ 4esn0k这不是一个错误.您的号码有太多数字,在64位二进制格式IEEE 754号码中不能有那么多精度.例如,`18014398509481984 == 18014398509481985`. (4认同)
  • 对于来自Google搜索`divmod`的rubyists,你可以这样实现:```function divmod(x,y){var div = Math.trunc(x/y); var rem = x%y; return [div,rem]; ```` (3认同)

小智 26

var remainder = x % y;
return (x - remainder) / y;
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,当 x = -100 时,该版本未通过测试,因为它返回 -34 而不是 -33。 (2认同)

Édi*_*ças 14

您可以使用该函数parseInt来获取截断的结果.

parseInt(a/b)
Run Code Online (Sandbox Code Playgroud)

要获得余数,请使用mod运算符:

a%b
Run Code Online (Sandbox Code Playgroud)

parseInt有一些字符串的缺陷,以避免使用基数为10的radix参数

parseInt("09", 10)
Run Code Online (Sandbox Code Playgroud)

在某些情况下,数字的字符串表示形式可以是科学记数法,在这种情况下,parseInt将产生错误的结果.

parseInt(100000000000000000000000000000000, 10) // 1e+32
Run Code Online (Sandbox Code Playgroud)

此调用将生成1作为结果.

  • 应尽可能避免使用`parseInt`.这是Douglas Crockford的警告:"如果字符串的第一个字符是0,那么字符串将在base 8而不是base 10中进行计算.在base 8中,8和9不是数字,所以parseInt("08")和parseInt ("09")产生0作为结果.这个错误导致解析日期和时间的程序出现问题.幸运的是,parseInt可以取一个基数参数,这样parseInt("08",10)就会产生8.我建议你总是这样做提供基数参数." http://archive.oreilly.com/pub/a/javascript/excerpts/javascript-good-parts/awful-parts.html (7认同)
  • 仅仅因为事物最初并不打算以某种方式使用,这并不意味着您不应该这样做。这个答案有效。 (3认同)
  • 在一个部门,我希望收到一个数字,而不是一个字符串,但这是一个好点. (2认同)
  • @Powers所以添加基数.他没有说应该避免使用"parseInt"; 只是有一些需要注意的问题._你必须意识到这些事情,并准备好应对._ (2认同)
  • 永远不要用数字参数调用`parseInt`.`parseInt`应该解析部分数字字符串,而不是截断数字. (2认同)

小智 9

我通常使用:

const quotient =  (a - a % b) / b;
const remainder = a % b;
Run Code Online (Sandbox Code Playgroud)

它可能不是最优雅的,但是可以工作。

  • 很好的解决方案,因为它避免了解析或截断浮点数的丑陋。 (3认同)
  • 如果同时需要商和余数,则首先计算余数,然后在商表达式中重用该值,即quotient =(a-余数)/ b; (3认同)
  • 余数=a%b;商 = (a - 余数) / b; (3认同)

Cyb*_*ght 6

JavaScript根据数学定义计算负数的底限和非整数的其余部分.

FLOOR定义为"小于参数的最大整数",因此:

  • 正数:FLOOR(X)= X的整数部分;
  • 负数:FLOOR(X)= X的整数部分减1(因为它必须比参数小,即更负!)

REMAINDER被定义为除法的"遗留"(欧几里德算术).当被除数不是整数时,商通常也不是整数,即没有余数,但如果商被强制为整数(当有人试图获得余数或模数时会发生这种情况)浮点数),显然会有一个非整数"遗留".

JavaScript确实按预期计算了所有内容,因此程序员必须小心提出正确的问题(人们应该小心回答问题!)Yarin的第一个问题不是"X乘Y的整数除法是什么",但是,相反,"给定整数进入另一个整数的次数".对于正数,两者的答案是相同的,但不是负数,因为整数除法(除数除数)将比数字(除数)"进入"另一个(被除数)的次数小-1.换句话说,FLOOR将返回负数的整数除法的正确答案,但Yarin没有问这个!

gammax回答正确,该代码按Yarin的要求工作.另一方面,塞缪尔错了,我猜他没有做数学,或者他会看到它确实有效(同样,他没有说他的例子的除数是什么,但我希望它是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,Remainder = -0.3800000000000079

是的,我注意到,那里存在精确问题,但我没有时间检查它(我不知道它是Firefox,Windows 7还是我的CPU的FPU的问题).但是,对于Yarin的问题,只涉及整数,gammax的代码完美无缺.


Aet*_*ity 5

Math.floor(operation) 返回操作的向下舍入值.

第一个问题的例子:

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

console.log(z);
Run Code Online (Sandbox Code Playgroud)

安慰:

15

第二个问题的例子:

var x = 14;
var y = 5;
var z = Math.floor(x%y);

console.log(x);
Run Code Online (Sandbox Code Playgroud)

安慰:

4


nki*_*tku 5

使用:

const idivmod = (a, b) => [a/b |0, a%b];
Run Code Online (Sandbox Code Playgroud)

还有一个正在研究的提案: Modulus and Extra Integer Math