# Modulo in JavaScript - large number

•  06-09-2019
•  |
•

Question

I try to calculate with JS' modulo function, but don't get the right result (which should be 1). Here is a hardcoded piece of code.

``````var checkSum = 210501700012345678131468;

Result: 66
``````

Whats the problem here?

Regards, Benedikt

Solution

A bunch of improvements to Benedikt's version: "cRest += '' + cDivident;" is a bugfix; parseInt(divisor) makes it possible to pass both arguments as strings; check for empty string at the end makes it always return numerical values; added var statements so it's not using global variables; converted foreach to old-style for so it works in browsers with older Javascript; fixed the cRest == 0; bug (thanks @Dan.StackOverflow).

```function modulo (divident, divisor) {
var cDivident = '';
var cRest = '';

for (var i in divident ) {
var cChar = divident[i];
var cOperator = cRest + '' + cDivident + '' + cChar;

if ( cOperator < parseInt(divisor) ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) {
cRest = '';
}
cDivident = '';
}

}
cRest += '' + cDivident;
if (cRest == '') {
cRest = 0;
}
return cRest;
}
```

OTHER TIPS

For an IBAN calculation form a normal bankaccount number I end up with a very large number contained in a string datatype. From this large number I have to find the rest when divided by 97 -> large number % 97.

As soon as I convert the datatype to an integer I get an overflow resulting in a negative integer and eventually a wrong rest value. As I saw some verbose pieces of code (which also gave wrong outcome), I could not resist to share my own. Credits go to Finding Modulus of a Very Large Number with a Normal Number

``````modulo: function(divident, divisor) {
var partLength = 10;

while (divident.length > partLength) {
var part = divident.substring(0, partLength);
divident = (part % divisor) +  divident.substring(partLength);
}

return divident % divisor;
}
``````

N.B. I use 10 positions here as this is smaller than the 15 (and some) positions of max integer in JavaScript, it results in a number bigger than 97 and it's a nice round number. The first two arguments matter.

looks like you've fallen victim to this: What is JavaScript's highest integer value that a Number can go to without losing precision?

just to reiterate what's in the other thread:

they are 64-bit floating point values, the largest exact integral value is 2^53. however, from the spec section [8.5: Number Type]:

Some ECMAScript operators deal only with integers in the range −2^31 through 2^31−1, inclusive, or in the range 0 through 2^32−1, inclusive. These operators accept any value of the Number type but first convert each such value to one of 2^32 integer values. See the descriptions of the ToInt32 and ToUint32 operators in sections 0 and 0, respectively

But credit where credit is due. Jimmy got the accepted answer over there for doing the legwork (well, googling).

Finally, my solution:

``````function modulo (divident, divisor) {
cDivident = '';
cRest = '';

for each ( var cChar in divident ) {
cOperator = cRest + '' + cDivident + '' + cChar;

if ( cOperator < divisor ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) cRest = '';
cDivident = '';
}

}

return cRest;
}
``````

For those who simply want to copy&paste a working (functional) solution in ES6 to check IBANs:

``````function isIBAN(s){
const rearranged = s.substring(4,s.length) + s.substring(0,4);
const numeric   = Array.from(rearranged).map(c =>(isNaN(parseInt(c)) ? (c.charCodeAt(0)-55).toString() : c)).join('');
const remainder = Array.from(numeric).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % 97,0);

return  remainder === 1;}
``````

You could even write it as a one-liner.

The modulo operation is performed on the array of integers storing the actual number (`divident`, applied as string to function):

``````function modulo(divident, divisor){
return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};
``````

This works because Modulo is distributive over addition, substraction and multiplication:

• (a+b)%m = ((a%m)+(b%m))%m
• (a-b)%m = ((a%m)-(b%m))%m
• (ab)%m = ((a%m)(b%m))%m

The IBAN function transpiled to ES5 looks like:

``````function (s) {
var rearranged = s.substring(4, s.length) + s.substring(0, 4);
var numeric = Array.from(rearranged).map(function (c) { return (isNaN(parseInt(c)) ? (c.charCodeAt(0) - 55).toString() : c); }).join('');
var remainder = Array.from(numeric).map(function (c) { return parseInt(c); }).reduce(function (remainder, value) { return (remainder * 10 + value) % 97; }, 0);
return remainder === 1;
};
``````

Silent Matt has developed a Javascript library for Big Integers. It could solve this issue too.