1171

JavaScript中,我如何获得:

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

18 回答 18

1571

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

var quotient = Math.floor(y/x);
var remainder = y % x;
于 2010-11-19T18:55:34.843 回答
451

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

var num = ~~(a / b);

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

这似乎也是正确的:

var num = (a / b) >> 0;
于 2010-11-19T19:14:06.183 回答
272

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

于 2013-06-20T15:42:18.730 回答
219

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

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

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

于 2014-03-10T17:30:08.943 回答
42

我通常使用:

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

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

于 2017-05-19T22:29:08.070 回答
36
var remainder = x % y;
return (x - remainder) / y;
于 2013-02-14T06:48:59.787 回答
24

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

parseInt(a/b)

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

a%b

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

parseInt("09", 10)

在某些情况下,数字的字符串表示可以是科学计数法,在这种情况下,parseInt 会产生错误的结果。

parseInt(100000000000000000000000000000000, 10) // 1e+32

此调用将产生 1 作为结果。

于 2015-04-13T17:17:16.470 回答
6

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

一个问题的例子:

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

console.log(z);

安慰:

15

第二个问题的例子:

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

console.log(x);

安慰:

4

于 2014-11-01T00:22:12.887 回答
5

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:进入 = -28,余数 = -0.3800000000000079

是的,我注意到了,那里有一个精度问题,但我没有时间检查它(我不知道这是 Firefox、Windows 7 还是我的 CPU 的 FPU 的问题)。不过,对于 Yarin 的问题,它只涉及整数,gammax 的代码可以完美运行。

于 2014-02-27T19:23:16.277 回答
4
const idivmod = (a, b) => [a/b |0, a%b];

还有一个关于它的提案 Modulus and Additional Integer Math

于 2020-11-25T13:55:16.877 回答
3

Alex Moore-Niemi的评论作为答案:

对于来自 Google 的 Rubyists 搜索divmod,您可以这样实现它:

function divmod(x, y) {
  var div = Math.trunc(x/y);
  var rem = x % y;
  return [div, rem];
}

结果:

// [2, 33]
于 2017-07-06T20:50:42.923 回答
1

计算页数可以一步完成:Math.ceil(x/y)

于 2017-11-11T15:48:53.867 回答
1
 function integerDivison(dividend, divisor){
    
        this.Division  = dividend/divisor;
        this.Quotient = Math.floor(dividend/divisor);
         this.Remainder = dividend%divisor;
        this.calculate = ()=>{
            return {Value:this.Division,Quotient:this.Quotient,Remainder:this.Remainder};
        }
         
    }

  var divide = new integerDivison(5,2);
  console.log(divide.Quotient)      //to get Quotient of two value 
  console.log(divide.division)     //to get Floating division of two value 
  console.log(divide.Remainder)     //to get Remainder of two value 
  console.log(divide.calculate())   //to get object containing all the values
于 2020-11-30T08:58:37.593 回答
1

如果您只是用 2 的幂除,则可以使用位运算符:

export function divideBy2(num) {
  return [num >> 1, num & 1];
}

export function divideBy4(num) {
  return [num >> 2, num & 3];
}

export function divideBy8(num) {
  return [num >> 3, num & 7];
}

(第一个是商,第二个是余数)

于 2017-09-13T13:25:52.397 回答
0

您也可以使用三元来决定如何处理正整数和负整数值。

var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1

如果这个数字是正数,一切都很好。如果数字是负数,它会加 1,因为 Math.floor 处理负数的方式。

于 2015-06-08T12:56:40.947 回答
0

这将始终截断为零。不知道是否为时已晚,但它是这样的:

function intdiv(dividend, divisor) { 
    divisor = divisor - divisor % 1;
    if (divisor == 0) throw new Error("division by zero");
    dividend = dividend - dividend % 1;
    var rem = dividend % divisor;
    return { 
        remainder: rem, 
        quotient: (dividend - rem) / divisor
    };
}
于 2017-05-11T13:59:24.017 回答
0

如果您需要计算 JS 运行时无法表示的非常大整数的余数(任何大于 2^32 的整数都表示为浮点数,因此它会失去精度),您需要做一些技巧。

这对于检查我们日常生活中许多情况下存在的许多校验位(银行帐号、信用卡等)尤为重要

首先,您需要将您的数字作为字符串(否则您已经失去了精度并且其余的没有意义)。

str = '123456789123456789123456789'

您现在需要将字符串分成更小的部分,足够小,以便任何余数和一段字符串的串联可以容纳 9 位数字。

digits = 9 - String(divisor).length

准备一个正则表达式来拆分字符串

splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')

例如,如果digits是 7,则正则表达式是

/.{1,7}(?=(.{7})+$)/g

它匹配最大长度为 7 的非空子字符串,后跟((?=...)是正向前瞻)多个 7 的字符。“g”是让表达式遍历所有字符串,而不是在第一次匹配时停止。

现在将每个部分转换为整数,并通过以下方式计算余数reduce(加回之前的余数 - 或 0 - 乘以 10 的正确幂):

reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor

由于“减法”余数算法,这将起作用:

n mod d = (n - kd) mod d

它允许用其余数替换数字的十进制表示的任何“初始部分”,而不影响最终余数。

最终代码如下所示:

function remainder(num, div) {
  const digits = 9 - String(div).length;
  const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
  const mult = Math.pow(10, digits);
  const reducer = (rem, piece) => (rem * mult + piece) % div;

  return str.match(splitter).map(Number).reduce(reducer, 0);
}
于 2018-09-19T10:11:32.750 回答
0

这是一种方法。(我个人不会这样做,但我认为这是一个有趣的例子)

function intDivide(numerator, denominator) {
  return parseInt((numerator/denominator).toString().split(".")[0]);
}

let x = intDivide(4,5);
let y = intDivide(5,5);
let z = intDivide(6,5);
console.log(x);
console.log(y);
console.log(z);

于 2020-11-12T23:10:05.293 回答