ChatGPT解决这个技术问题 Extra ChatGPT

How to perform an integer division, and separately get the remainder, in JavaScript?

In JavaScript, how do I get:

The whole number of times a given integer goes into another? The remainder?


P
Palec

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;

% works on floats in JavaScript (this differs from many other languages), which is perhaps not desired: 3.5 % 2 evaluates to 1.5. Make sure to handle (parseInt, floor, etc.) as required
The integral part of -4.5 in mathematics is -5, as -5 is the "highest possible integral number that is still lower than -4.5".
However, whatever you decide to do about negative numbers, it should be consistent across the quotient and the remainder. Using floor and % together is not consistent in that way. Either use trunc instead of floor (thereby permitting negative remainders) or use subtraction to get the remainder (rem = y - div * x).
1. If you're going to compute the remainder rem anyway, you can get the quotient div faster without flooring: (y - rem) / x. 2. By the way the modulo operation by Donald Knuth's recommended definition (sign-matches-divisor, not the remainder i.e. Euclidean modulus, nor the JavaScript sign-matches-dividend) is what we can code in JavaScript as function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }.
-9 / 2 = -4.5. You then take the floor of -4.5, which is -5. Remember that -5 is less than -4.5, and the floor operation is defined as the largest integer less than a given value.
w
wvdz

I'm no expert in bitwise operators, but here's another way to get the whole number:

var num = ~~(a / b);

This will work properly for negative numbers as well, while Math.floor() will round in the wrong direction.

This seems correct as well:

var num = (a / b) >> 0;

Another one, whose purpose I just spent the last 20 minutes trying to figure out, is apparently a/b | 0
@user113716 @BlueRaja Bitwise operations makes sense only on integer-types and JS (of course) knows that. ~~int, int | 0 and int >> 0 doesn't modify initial argument, but make interpreter pass integral part to operator.
floor hardly rounds in the wrong direction, given its name - just not the direction that people generally want though!
That's a buu buu. a = 12447132275286670000; b = 128 Math.floor(a/b) -> 97243220900677100 and ~~(a/b) -> -1231452688.
Be careful with precedence. ~~(5/2) --> 2 as does (5/2)>>0 --> 2, but ~~(5/2) + 1 --> 3, while ~~(5/2)>>0 + 1 --> 1. ~~ is a good choice because the precedence is more appropriate.
K
KalEl

I did some speed tests on 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

The above is based on 10 million trials for each.

Conclusion: Use (a/b>>0) (or (~~(a/b)) or (a/b|0)) to achieve about 20% gain in efficiency. Also keep in mind that they are all inconsistent with Math.floor, when a/b<0 && a%b!=0.


I find Math.floor() has more stable performance than others do. it is less up-and-down
Note that optimizing integer division for speed would make sense only if you're doing it a lot. In any other case I would recommend choosing the simplest one (whichever seems simplest to you and your coworkers).
@m01 totally agree - there's way too much of a focus on stuff like this online
@m01 But which is harder: learning about Math.floor and the who-knows-how-many other API functions, or learning about the ~ (bitwise-not) operator and how bitwise operations work in JS and then understanding the effect of double tilde?
Well, if your coworkers aren't programming chips in assembler, they'll likely understand Math.floor better. And even if not, this one is googleable.
C
Community

ES6 introduces the new Math.trunc method. This allows to fix @MarkElliot's answer to make it work for negative numbers too:

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

Note that Math methods have the advantage over bitwise operators that they work with numbers over 231.


var y =18014398509481984; var x= 5; div = ? - bug ?
@4esn0k It's not a bug. Your number has too many digits, you can't have that much precision in a 64-bit binary format IEEE 754 number. For example, 18014398509481984 == 18014398509481985.
18014398509481984 == 2**54, and i specially used this number, because it is represented exactly in binary64 format. and the answer is represented exactly too
I think the choice is simple: You need support for numbers up to 32 bits signed? Use ~~(x/y). Need to support bigger numbers up to 54 bits signed? Use Math.trunc if you have it, or Math.floor otherwise (correct for negative numbers). Need to support even bigger numbers? Use some big number library.
for rubyists here from google in search of divmod, you can implement it as such: function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
D
Dem Pilafian

I normally use:

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

It's probably not the most elegant, but it works.


Nice solution because it avoids the ugliness of parsing or truncating a float.
if you need both quotient and remainder, calculate the remainder first and then reuse that value in the expression for the quotient, i.e. quotient = (a - remainder) / b;
remainder = a % b; quotient = (a - remainder) / b;
g
gammax
var remainder = x % y;
return (x - remainder) / y;

This version unfortunately fails the test when x = -100 because it returns -34 instead of -33.
what about "var x = 0.3; var y = 0.01;" ? (thanks to github.com/JuliaLang/julia/issues/4156#issuecomment-23324163)
Actually, @Samuel, with negative values, this method returns correct results, or at least it returns the same values as the method using Math.trunc :). I checked with 100,3; -100,3; 100,-3 and -100,-3. Of course, a lot of time has passed since your comment and things change.
É
Édipo Costa Rebouças

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.


parseInt should be avoided when possible. Here is Douglas Crockford's warning: "If the first character of the string is 0, then the string is evaluated in base 8 instead of base 10. In base 8, 8 and 9 are not digits, so parseInt("08") and parseInt("09") produce 0 as their result. This error causes problems in programs that parse dates and times. Fortunately, parseInt can take a radix parameter, so that parseInt("08", 10) produces 8. I recommend that you always provide the radix parameter." archive.oreilly.com/pub/a/javascript/excerpts/…
In a division, I expect receive a number, not a string, but this is a good point.
@Powers so add the radix. He doesn't say parseInt should be avoided; just that there are some gotchas to be aware of. You must be aware of these things and be prepared to cope.
Never call parseInt with a number argument. parseInt is supposed to parse partially-numerical strings, not truncate numbers.
Just because things are not originally meant to be used a certain way, it doesn't mean you shouldn't. This answer works.
T
Teocci

Math.floor(operation) returns the rounded down value of the operation.

Example of 1st question:

const x = 5; const y = 10.4; const z = Math.floor(x + y); console.log(z);

Example of 2nd question:

const x = 14; const y = 5; const z = Math.floor(x % y); console.log(x);


L
László Papp

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.


n
nkitku
const idivmod = (a, b) => [a/b |0, a%b];

there is also a proposal working on it Modulus and Additional Integer Math


A
Alex

Alex Moore-Niemi's comment as an answer:

For Rubyists here from Google in search of divmod, you can implement it as such:

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

Result:

// [2, 33]

Usually, divmod uses floored division (Math.floor), which differs from truncated division (Math.trunc) when negative numbers are involved. This is the case for NPM divmod package, Ruby divmod, SWI-Prolog divmod and probably many other implementations, too.
Truncated division gives more naturally looking results than floored division, but compatibility trumps that, IMO. Maybe, there are mathematical or performance reasons for using floored division, too. Note that usually, divmod exists because it is performs twice as fast as computing the two operations separately. Providing such a function without this performance benefit might be confusing.
K
Konstantin Möllers

If you are just dividing with powers of two, you can use bitwise operators:

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];
}

(The first is the quotient, the second the remainder)


Generally, function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }.
S
Sandeep Kumar
 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

J
Josh Weston

You can use ternary to decide how to handle positive and negative integer values as well.

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

If the number is a positive, all is fine. If the number is a negative, it will add 1 because of how Math.floor handles negatives.


b
bzim

This will always truncate towards zero. Not sure if it is too late, but here it goes:

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
    };
}

u
user1920925

Calculating number of pages may be done in one step: Math.ceil(x/y)


I don't see how this provides the remainder.
r
rewritten

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);
}

D
Daniel

Here is a way to do this. (Personally I would not do it this way, but thought it was a fun way to do it for an example)

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);