javascript how to tell if one number is a multiple of another

89,478

Solution 1

Use the % (modulus) operator in Javascript and PHP, which returns the remainder when a is divided by b in a % b. The remainder will be zero when a is a multiple of b.

Ex.

//Javascript
var result = userLength * basePrice;     //Get result
if(result % patternLength){              //Check if there is a remainder
  var remainder = result % patternLength; //Get remainder
  if(remainder >= patternLength / 2)      //If the remainder is larger than half of patternLength, then go up to the next mulitple
    result += patternLength - remainder;
  else                                    //Else - subtract the remainder to go down
    result -= remainder;
}
result = Math.round(result * 100) / 100;  //Round to 2 decimal places

Solution 2

You can use the modulus to find the remainder after a division and then if the remainder is equal to zero then it's a multiple.

//x and y are both integers
var remainder = x % y;
if (remainder == 0){
//x is a multiple of y
} else {
//x is not a multiple of y
}

If the numbers your using could be to 2dp, the modulus should still work, if not, multiply both by 100 first then carry out the above check.

Solution 3

This avoids JavaScript precision issues (if your factor y has less than 5 decimal places).

function isMultiple(x, y) {
    return Math.round(x / y) / (1 / y) === x;
}

The above algorithm will fail for very small factors <= 1e-5. The following is a solution that will work for all values that would be <= Number.MAX_SAFE_INTEGER with the decimal point removed, i.e. most values that would have up to 16 digits and all values that would have up to 15 digits, i.e. most non-scientific values.

If you are working with scientific values, use big.js.

function decimalPlaces(x) {
    const str = ''+ +x;
    const dindex = str.indexOf('.');
    const eindex = str.indexOf('e');
    return (
        (dindex < 0 ? 0 : (eindex < 0 ? str.length : eindex) - dindex - 1) +
        (eindex < 0 ? 0 : Math.max(0, -parseInt(str.slice(eindex + 1)))));
}

function isMultiple(x, y) {
    const xplaces = decimalPlaces(x);
    const yplaces = decimalPlaces(y);
    if (xplaces > yplaces) {
        return false;
    }
    const pfactor = Math.pow(10, yplaces);
    return Math.round(pfactor * x) % Math.round(pfactor * y) === 0;
}

[
    [2.03, 0.01],
    [2.03, 0.0123],
    [2.029999999999, 0.01],
    [2.030000000001, 0.01],
    [0.03, 0.01],
    [240, 20],
    [240, 21],
    [1, 1],
    [4, 2],
    [6, 3],
    [6, 4],
    [1.123456, 0.000001]
].forEach(([number, multiple]) => {
    const result = isMultiple(number, multiple);
    console.log(`isMultiple (${number}, ${multiple}) =`, result);
});

Solution 4

In javascript there is the remainder operator (similar to most languages with a c-like syntax).

Let x = length and y = price and z = product of x*y

var remainder = (z % x) / 100;

if (remainder === 0) {
   // z is a multiple of x
}

To get the closest x multiple to your result z you could round the result up (or down) using ceil or floor functions in the Math library.

if (r >= x / 2) {
    a = Math.ceil(z/x)*x;
}
else {
    a = Math.floor(z/x)*x;
}

Then round to two decimal places

Math.round(a / 100) * 100;

Solution 5

Not sure if I really understood the task as it seems quite simple to me, but have a look at this PHP code:

// --- input ---
$pattern = 12.34;
$input = 24.68;
$precision = 2; // number of decimals

// --- calculation ---

// switch to "fixed point":
$base = pow(10, $precision);
$pattern = round($pattern * $base);
$input = round($input * $base);

if ($input % $pattern) {
  // not an exact multiple
  $input = ceil($input / $pattern) * $pattern;
} else {
  // it is an exact multiple
}

// back to normal precision:
$pattern /= $base;
$input /= $base;

This can be easily translated to JavaScript.

$input will be the next closest multiple of the pattern. If you just need that and don't need to know if it actually was a multiple you could also simply do something like this:

$input = ceil($input * 100 / $pattern) * $pattern / 100;
Share:
89,478
totallyNotLizards
Author by

totallyNotLizards

Proud father, professional web developer, and all round lovable rogue

Updated on August 10, 2021

Comments

  • totallyNotLizards
    totallyNotLizards over 2 years

    I'm building a fairly calculation-heavy cart for a fabric store and have found myself needing to do a calculation on user inputted length * the baseprice per metre, but then checking the result to see if it is a multiple of the pattern length. If it is not a multiple, I need to find the closest multiple of the pattern length and change the result to that.

    I need to also be able to do exactly the same calculation in PHP, but if anyone can help me out with the maths I can port anything that needs to be translated myself.

    I am using jQuery 1.6.2 and already have the first part of the calculation done, I just need to check the result of (metres*price) against the pattern length.

    Any help greatly appreciated

    EDIT: These calculations all involve 2 decimal places for both the price and the pattern length. User inputted length may also contain decimals.

  • Teodor
    Teodor over 12 years
    Just remember to round the number so you don't get any floating point problems like stackoverflow.com/questions/3966484/…
  • totallyNotLizards
    totallyNotLizards over 12 years
    facepalm :) i had though of modulus but didnt think through what i could do with the remainder. this works for me, thanks muchly.
  • thednp
    thednp almost 9 years
    Hey, I don't want to write a duplicate, you mean you would write a quick bool for if ( a % b ) {} to return true if b is multiplier of a ?? EDIT: the below answer explains better for my case.
  • Adam Leggett
    Adam Leggett over 4 years
    JS number precision issues make this no good for a wide variety of cases.