如何在 JavaScript 中执行整数除法并分别得到余数?

IT技术 javascript math modulo integer-division
2021-01-28 20:48:09

JavaScript 中,我如何获得:

  1. 给定整数进入另一个整数的次数?
  2. 其余的?
6个回答

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

var quotient = Math.floor(y/x); or parseInt(y/x);
var remainder = y % x;
-4.5 在数学中的整数部分是 -5,因为 -5 是“仍然低于 -4.5 的最大可能整数”。
2021-03-18 20:48:09
% 适用于 JavaScript 中的浮点数(这与许多其他语言不同),这可能不是我们想要的:3.5 % 2计算结果为 1.5。确保按要求处理(parseInt、floor 等)
2021-03-25 20:48:09
1. 如果你rem无论如何都要计算余数,你可以div更快地得到商而不用地板:(y - rem) / x2. 顺便说一下,Donald Knuth 推荐的定义(符号-匹配-除数,不是余数,即欧几里得模数,也不是 JavaScript 符号-匹配-被除数)的模运算是我们可以在 JavaScript 中编码的内容function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
2021-03-29 20:48:09
-9 / 2 = -4.5。然后你取 -4.5 的地板,也就是 -5。请记住,-5 小于 -4.5,并且地板运算被定义为小于给定值的最大整数。
2021-04-02 20:48:09
但是,无论您决定对负数做什么,商和余数都应该保持一致。以这种方式使用floor%并不一致。使用trunc而不是floor(从而允许负余数)或使用减法来获得余数 ( rem = y - div * x)。
2021-04-10 20:48:09

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

var num = ~~(a / b);

这也适用于负数,但Math.floor()会朝错误的方向舍入。

这似乎也是正确的:

var num = (a / b) >> 0;
@user113716 @BlueRaja 按位运算仅对整数类型有意义,而 JS(当然)知道这一点。~~int,int | 0并且int >> 0不修改初始参数,而是使解释器将组成部分传递给运算符。
2021-03-18 20:48:09
小心优先。~~(5/2) --> 2一样(5/2)>>0 --> 2,但是~~(5/2) + 1 --> 3,同时~~(5/2)>>0 + 1 --> 1~~是一个不错的选择,因为优先级更合适。
2021-03-25 20:48:09
那是布布布。a = 12447132275286670000; b = 128 Math.floor(a/b)->97243220900677100~~(a/b)-> -1231452688
2021-04-02 20:48:09
另一个,我刚刚花了最后 20 分钟试图弄清楚它的目的,显然是 a/b | 0
2021-04-08 20:48:09
floor 顾名思义,它几乎不会朝着错误的方向前进——尽管这不是人们通常想要的方向!
2021-04-10 20:48:09

我在 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

以上基于每个试验 1000 万次。

结论:使用(a/b>>0)(或(~~(a/b))(a/b|0))可实现约 20% 的效率增益。还要记住,它们都与Math.floor, when不一致a/b<0 && a%b!=0

需要注意的是优化整数除法的速度才有意义只有当你正在做的很多在任何其他情况下,我都建议选择最简单的(对您和您的同事来说最简单的那个)。
2021-03-12 20:48:09
好吧,如果你的同事不是用汇编程序编程芯片,他们可能会Math.floor更好地理解即使没有,这个也可以用谷歌搜索。
2021-03-17 20:48:09
@m01 完全同意 - 网上对此类内容的关注太多了
2021-03-19 20:48:09
我发现 Math.floor() 的性能比其他人更稳定。它少了上下
2021-03-26 20:48:09
@m01 但哪个更难:了解Math.floor谁知道还有多少其他 API 函数,或者了解~(按位非)运算符以及按位运算在 JS 中的工作原理,然后了解双波浪号的效果?
2021-03-28 20:48:09

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

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

请注意,Math与按位运算符相比方法的优势在于它们可以处理超过 2 31 的数字

18014398509481984 == 2**54,我特地用了这个数字,因为它是用binary64格式准确表示的。答案也准确地表示出来
2021-03-13 20:48:09
我认为选择很简单:您需要支持最多 32 位有符号的数字吗?使用~~(x/y). 需要支持高达 54 位有符号的更大数字吗?Math.trunc如果有,请使用Math.floor否则使用(对负数更正)。需要支持更大的数字吗?使用一些大数字库。
2021-03-20 20:48:09
@4esn0k 这不是错误。您的数字有太多位数,在 64 位二进制格式 IEEE 754 数字中不能有那么高的精度。例如,18014398509481984 == 18014398509481985
2021-03-30 20:48:09
var y =18014398509481984; 无功x= 5; div = ? - 漏洞 ?
2021-04-08 20:48:09
对于来自 google 的 ruby​​ists 来搜索divmod,你可以这样实现它:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
2021-04-08 20:48:09

我通常使用:

const quotient =  (a - a % b) / b;
const remainder = a % b;

它可能不是最优雅的,但它有效。

余数 = a % b; 商 = (a - 余数) / b;
2021-03-12 20:48:09
如果您同时需要商和余数,请先计算余数,然后在商的表达式中重复使用该值,即 quotient = (a - 余数) / b;
2021-03-20 20:48:09
不错的解决方案,因为它避免了解析或截断浮点数的丑陋。
2021-03-28 20:48:09