mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add isPowerOfTwo functions.
This commit is contained in:
parent
beb8501aca
commit
74b93d36cb
@ -50,6 +50,7 @@ a set of rules that precisely define a sequence of operations.
|
|||||||
* [Least Common Multiple](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple) (LCM)
|
* [Least Common Multiple](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple) (LCM)
|
||||||
* [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition)
|
* [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition)
|
||||||
* [Sieve of Eratosthenes](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit
|
* [Sieve of Eratosthenes](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit
|
||||||
|
* [Is Power of Two](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/is-power-of-two) - check if the number is power of two (naive and bitwise algorithms)
|
||||||
* **Sets**
|
* **Sets**
|
||||||
* [Cartesian Product](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - product of multiple sets
|
* [Cartesian Product](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - product of multiple sets
|
||||||
* [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of a set
|
* [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of a set
|
||||||
|
52
src/algorithms/math/is-power-of-two/README.md
Normal file
52
src/algorithms/math/is-power-of-two/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Is a power of two
|
||||||
|
|
||||||
|
Given a positive integer, write a function to find if it is
|
||||||
|
a power of two or not.
|
||||||
|
|
||||||
|
**Naive solution**
|
||||||
|
|
||||||
|
In naive solution we just keep dividing the number by two
|
||||||
|
unless the number becomes `1` and every time we do so we
|
||||||
|
check that remainder after division is always `0`. Otherwise
|
||||||
|
the number can't be a power of two.
|
||||||
|
|
||||||
|
**Bitwise solution**
|
||||||
|
|
||||||
|
Powers of two in binary form always have just one bit.
|
||||||
|
The only exception is with a signed integer (e.g. an 8-bit
|
||||||
|
signed integer with a value of -128 looks like: `10000000`)
|
||||||
|
|
||||||
|
```
|
||||||
|
1: 0001
|
||||||
|
2: 0010
|
||||||
|
4: 0100
|
||||||
|
8: 1000
|
||||||
|
```
|
||||||
|
|
||||||
|
So after checking that the number is greater than zero,
|
||||||
|
we can use a bitwise hack to test that one and only one
|
||||||
|
bit is set.
|
||||||
|
|
||||||
|
```
|
||||||
|
number & (number - 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
For example for number `8` that operations will look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
1000
|
||||||
|
- 0001
|
||||||
|
----
|
||||||
|
0111
|
||||||
|
|
||||||
|
1000
|
||||||
|
& 0111
|
||||||
|
----
|
||||||
|
0000
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [GeeksForGeeks](https://www.geeksforgeeks.org/program-to-find-whether-a-no-is-power-of-two/)
|
||||||
|
- [Bitwise Solution on Stanford](http://www.graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2)
|
||||||
|
- [Binary number subtraction on YouTube](https://www.youtube.com/watch?v=S9LJknZTyos&t=0s&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&index=66)
|
@ -0,0 +1,30 @@
|
|||||||
|
import isPowerOfTwo from '../isPowerOfTwo';
|
||||||
|
|
||||||
|
describe('isPowerOfTwo', () => {
|
||||||
|
it('should throw an exception when trying to apply function to negative number', () => {
|
||||||
|
const isNegativePowerOfTwo = () => {
|
||||||
|
isPowerOfTwo(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(isNegativePowerOfTwo).toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check if the number is made by multiplying twos', () => {
|
||||||
|
expect(isPowerOfTwo(0)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(1)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(2)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwo(3)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(4)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwo(5)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(6)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(7)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(8)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwo(10)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(12)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(16)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwo(31)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwo(64)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwo(1024)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwo(1023)).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,30 @@
|
|||||||
|
import isPowerOfTwoBitwise from '../isPowerOfTwoBitwise';
|
||||||
|
|
||||||
|
describe('isPowerOfTwoBitwise', () => {
|
||||||
|
it('should throw an exception when trying to apply function to negative number', () => {
|
||||||
|
const isNegativePowerOfTwo = () => {
|
||||||
|
isPowerOfTwoBitwise(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(isNegativePowerOfTwo).toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check if the number is made by multiplying twos', () => {
|
||||||
|
expect(isPowerOfTwoBitwise(0)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(1)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(2)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwoBitwise(3)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(4)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwoBitwise(5)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(6)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(7)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(8)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwoBitwise(10)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(12)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(16)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwoBitwise(31)).toBeFalsy();
|
||||||
|
expect(isPowerOfTwoBitwise(64)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwoBitwise(1024)).toBeTruthy();
|
||||||
|
expect(isPowerOfTwoBitwise(1023)).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
30
src/algorithms/math/is-power-of-two/isPowerOfTwo.js
Normal file
30
src/algorithms/math/is-power-of-two/isPowerOfTwo.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @param {number} number
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
export default function isPowerOfTwo(number) {
|
||||||
|
// Don't work with negative numbers.
|
||||||
|
if (number < 0) {
|
||||||
|
throw new Error('Please provide positive number');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 and 1 are not powers of two.
|
||||||
|
if (number <= 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dividedNumber /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
31
src/algorithms/math/is-power-of-two/isPowerOfTwoBitwise.js
Normal file
31
src/algorithms/math/is-power-of-two/isPowerOfTwoBitwise.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* @param {number} number
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
export default function isPowerOfTwoBitwise(number) {
|
||||||
|
// Don't work with negative numbers.
|
||||||
|
if (number < 0) {
|
||||||
|
throw new Error('Please provide positive number');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 and 1 are not powers of two.
|
||||||
|
if (number <= 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Powers of two in binary look like this:
|
||||||
|
* 1: 0001
|
||||||
|
* 2: 0010
|
||||||
|
* 4: 0100
|
||||||
|
* 8: 1000
|
||||||
|
*
|
||||||
|
* Note that there is always exactly 1 bit set. The only exception is with a signed integer.
|
||||||
|
* e.g. An 8-bit signed integer with a value of -128 looks like:
|
||||||
|
* 10000000
|
||||||
|
*
|
||||||
|
* So after checking that the number is greater than zero, we can use a clever little bit
|
||||||
|
* hack to test that one and only one bit is set.
|
||||||
|
*/
|
||||||
|
return (number & (number - 1)) === 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user