diff --git a/src/algorithms/math/is-power-of-two/isPowerOfTwo.js b/src/algorithms/math/is-power-of-two/isPowerOfTwo.js index 6f7590dd..077dc383 100644 --- a/src/algorithms/math/is-power-of-two/isPowerOfTwo.js +++ b/src/algorithms/math/is-power-of-two/isPowerOfTwo.js @@ -1,24 +1,37 @@ /** - * @param {number} number + * @param {number|bigint} numeric value to check * @return {boolean} */ -export default function isPowerOfTwo(number) { +export default function isPowerOfTwo(x) { // 1 (2^0) is the smallest power of two. - if (number < 1) { - return false; + if (x <= 1) { + return x == 1; + } + + // guard clause to dispatch BigInts ASAP + if (typeof x == "bigint") { + // the bitwise alt works for any BigInt + // because bit operators are arbitrary-precision for them + return (x & (x - 1n)) === 0n; } // Let's find out if we can divide the number by two // many times without remainder. - let dividedNumber = number; - while (dividedNumber !== 1) { - if (dividedNumber % 2 !== 0) { - // For every case when remainder isn't zero we can say that this number - // couldn't be a result of power of two. + let dividedNum = x / 2; + while (dividedNum !== 1) { + if ( !Number.isInteger(dividedNum) ) { + /* + For every case when quotient is non-int we can say that this number + couldn't be a result of power of two (with integer exponent), + because checking the fractional part of a quotient is equivalent to checking if the remainder is 0, + and the remainder is the value of the least significant bit (with fractional part included). + All powers of 2 (but `1`) must have consecutive trailing zeros. + this also immediately dispatches non-int values of `x`, because neither rem nor quotient is an int + */ return false; } - dividedNumber /= 2; + dividedNum /= 2; } return true;