Integer division with remainder in JavaScript?

2019-01-01 16:33发布

In JavaScript, how do I get:

  1. the whole number of times a given integer goes into another?
  2. the remainder?

15条回答
残风、尘缘若梦
2楼-- · 2019-01-01 17:09
var remainder = x % y;
return (x - remainder) / y;
查看更多
栀子花@的思念
3楼-- · 2019-01-01 17:12

If you need to calculate the remainder for very large integers, which the JS runtime cannot represent as such (any integer greater than 2^32 is represented as a float and so it loses precision), you need to do some trick.

This is especially important for checking many case of check digits which are present in many instances of our daily life (bank account numbers, credit cards, ...)

First of all you need your number as a string (otherwise you have already lost precision and the remainder does not make sense).

str = '123456789123456789123456789'

You now need to split your string in smaller parts, small enough so the concatenation of any remainder and a piece of string can fit in 9 digits.

digits = 9 - String(divisor).length

Prepare a regular expression to split the string

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

For instance, if digits is 7, the regexp is

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

It matches a nonempty substring of maximum length 7, which is followed ((?=...) is a positive lookahead) by a number of characters that is multiple of 7. The 'g' is to make the expression run through all string, not stopping at first match.

Now convert each part to integer, and calculate the remainders by reduce (adding back the previous remainder - or 0 - multiplied by the correct power of 10):

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

This will work because of the "subtraction" remainder algorithm:

n mod d = (n - kd) mod d

which allows to replace any 'initial part' of the decimal representation of a number with its remainder, without affecting the final remainder.

The final code would look like:

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);
}
查看更多
其实,你不懂
4楼-- · 2019-01-01 17:13

I normally use (a - a % b) / b. It's probably not the most elegant, but it works.

查看更多
无色无味的生活
5楼-- · 2019-01-01 17:17

For some number y and some divisor x compute the quotient (quotient) and remainder (remainder) as:

var quotient = Math.floor(y/x);
var remainder = y % x;
查看更多
低头抚发
6楼-- · 2019-01-01 17:17

You can use the function parseInt to get a truncated result.

parseInt(a/b)

To get a remainder, use mod operator:

a%b

parseInt have some pitfalls with strings, to avoid use radix parameter with base 10

parseInt("09", 10)

In some cases the string representation of the number can be a scientific notation, in this case, parseInt will produce a wrong result.

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

This call will produce 1 as result.

查看更多
梦该遗忘
7楼-- · 2019-01-01 17:17

JavaScript calculates right the floor of negative numbers and the remainder of non-integer numbers, following the mathematical definitions for them.

FLOOR is defined as "the largest integer number smaller than the parameter", thus:

  • positive numbers: FLOOR(X)=integer part of X;
  • negative numbers: FLOOR(X)=integer part of X minus 1 (because it must be SMALLER than the parameter, i.e., more negative!)

REMAINDER is defined as the "left over" of a division (Euclidean arithmetic). When the dividend is not an integer, the quotient is usually also not an integer, i.e., there is no remainder, but if the quotient is forced to be an integer (and that's what happens when someone tries to get the remainder or modulus of a floating-point number), there will be a non-integer "left over", obviously.

JavaScript does calculate everything as expected, so the programmer must be careful to ask the proper questions (and people should be careful to answer what is asked!) Yarin's first question was NOT "what is the integer division of X by Y", but, instead, "the WHOLE number of times a given integer GOES INTO another". For positive numbers, the answer is the same for both, but not for negative numbers, because the integer division (dividend by divisor) will be -1 smaller than the times a number (divisor) "goes into" another (dividend). In other words, FLOOR will return the correct answer for an integer division of a negative number, but Yarin didn't ask that!

gammax answered correctly, that code works as asked by Yarin. On the other hand, Samuel is wrong, he didn't do the maths, I guess, or he would have seen that it does work (also, he didn't say what was the divisor of his example, but I hope it was 3):

Remainder = X % Y = -100 % 3 = -1

GoesInto = (X - Remainder) / Y = (-100 - -1) / 3 = -99 / 3 = -33

By the way, I tested the code on Firefox 27.0.1, it worked as expected, with positive and negative numbers and also with non-integer values, both for dividend and divisor. Example:

-100.34 / 3.57: GoesInto = -28, Remainder = -0.3800000000000079

Yes, I noticed, there is a precision problem there, but I didn't had time to check it (I don't know if it's a problem with Firefox, Windows 7 or with my CPU's FPU). For Yarin's question, though, which only involves integers, the gammax's code works perfectly.

查看更多
登录 后发表回答