javascript how to tell if one number is a multiple of another
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;
totallyNotLizards
Proud father, professional web developer, and all round lovable rogue
Updated on August 10, 2021Comments
-
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 over 12 yearsJust remember to round the number so you don't get any floating point problems like stackoverflow.com/questions/3966484/…
-
totallyNotLizards over 12 yearsfacepalm :) i had though of modulus but didnt think through what i could do with the remainder. this works for me, thanks muchly.
-
thednp almost 9 yearsHey, I don't want to write a duplicate, you mean you would write a quick
bool
forif ( a % b ) {}
to return true ifb
is multiplier ofa
?? EDIT: the below answer explains better for my case. -
Adam Leggett over 4 yearsJS number precision issues make this no good for a wide variety of cases.