Skip to content

Commit 98400e1

Browse files
Add is power of two (TheAlgorithms#970)
1 parent ebc3767 commit 98400e1

File tree

3 files changed

+243
-0
lines changed

3 files changed

+243
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* [Binary Coded Decimal](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/binary_coded_decimal.rs)
2121
* [Counting Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/counting_bits.rs)
2222
* [Highest Set Bit](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/highest_set_bit.rs)
23+
* [Is Power of Two](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/is_power_of_two.rs)
2324
* [N Bits Gray Code](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/n_bits_gray_code.rs)
2425
* [Previous Power of Two](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/find_previous_power_of_two.rs)
2526
* [Reverse Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/reverse_bits.rs)
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
//! Power of Two Check
2+
//!
3+
//! This module provides a function to determine if a given positive integer is a power of two
4+
//! using efficient bit manipulation.
5+
//!
6+
//! # Algorithm
7+
//!
8+
//! The algorithm uses the property that powers of two have exactly one bit set in their
9+
//! binary representation. When we subtract 1 from a power of two, all bits after the single
10+
//! set bit become 1, and the set bit becomes 0:
11+
//!
12+
//! ```text
13+
//! n = 0..100..00 (power of 2)
14+
//! n - 1 = 0..011..11
15+
//! n & (n - 1) = 0 (no intersections)
16+
//! ```
17+
//!
18+
//! For example:
19+
//! - 8 in binary: 1000
20+
//! - 7 in binary: 0111
21+
//! - 8 & 7 = 0000 = 0 ✓
22+
//!
23+
//! Author: Alexander Pantyukhin
24+
//! Date: November 1, 2022
25+
26+
/// Determines if a given number is a power of two.
27+
///
28+
/// This function uses bit manipulation to efficiently check if a number is a power of two.
29+
/// A number is a power of two if it has exactly one bit set in its binary representation.
30+
/// The check `number & (number - 1) == 0` leverages this property.
31+
///
32+
/// # Arguments
33+
///
34+
/// * `number` - An integer to check (must be non-negative)
35+
///
36+
/// # Returns
37+
///
38+
/// A `Result` containing:
39+
/// - `Ok(true)` - If the number is a power of two (including 0 and 1)
40+
/// - `Ok(false)` - If the number is not a power of two
41+
/// - `Err(String)` - If the number is negative
42+
///
43+
/// # Examples
44+
///
45+
/// ```
46+
/// use the_algorithms_rust::bit_manipulation::is_power_of_two;
47+
///
48+
/// assert_eq!(is_power_of_two(0).unwrap(), true);
49+
/// assert_eq!(is_power_of_two(1).unwrap(), true);
50+
/// assert_eq!(is_power_of_two(2).unwrap(), true);
51+
/// assert_eq!(is_power_of_two(4).unwrap(), true);
52+
/// assert_eq!(is_power_of_two(8).unwrap(), true);
53+
/// assert_eq!(is_power_of_two(16).unwrap(), true);
54+
///
55+
/// assert_eq!(is_power_of_two(3).unwrap(), false);
56+
/// assert_eq!(is_power_of_two(6).unwrap(), false);
57+
/// assert_eq!(is_power_of_two(17).unwrap(), false);
58+
///
59+
/// // Negative numbers return an error
60+
/// assert!(is_power_of_two(-1).is_err());
61+
/// ```
62+
///
63+
/// # Errors
64+
///
65+
/// Returns an error if the input number is negative.
66+
///
67+
/// # Time Complexity
68+
///
69+
/// O(1) - The function performs a constant number of operations regardless of input size.
70+
pub fn is_power_of_two(number: i32) -> Result<bool, String> {
71+
if number < 0 {
72+
return Err("number must not be negative".to_string());
73+
}
74+
75+
// Convert to u32 for safe bit operations
76+
let num = number as u32;
77+
78+
// Check if number & (number - 1) == 0
79+
// For powers of 2, this will always be true
80+
Ok(num & num.wrapping_sub(1) == 0)
81+
}
82+
83+
#[cfg(test)]
84+
mod tests {
85+
use super::*;
86+
87+
#[test]
88+
fn test_zero() {
89+
// 0 is considered a power of 2 by the algorithm (2^(-∞) interpretation)
90+
assert!(is_power_of_two(0).unwrap());
91+
}
92+
93+
#[test]
94+
fn test_one() {
95+
// 1 = 2^0
96+
assert!(is_power_of_two(1).unwrap());
97+
}
98+
99+
#[test]
100+
fn test_powers_of_two() {
101+
assert!(is_power_of_two(2).unwrap()); // 2^1
102+
assert!(is_power_of_two(4).unwrap()); // 2^2
103+
assert!(is_power_of_two(8).unwrap()); // 2^3
104+
assert!(is_power_of_two(16).unwrap()); // 2^4
105+
assert!(is_power_of_two(32).unwrap()); // 2^5
106+
assert!(is_power_of_two(64).unwrap()); // 2^6
107+
assert!(is_power_of_two(128).unwrap()); // 2^7
108+
assert!(is_power_of_two(256).unwrap()); // 2^8
109+
assert!(is_power_of_two(512).unwrap()); // 2^9
110+
assert!(is_power_of_two(1024).unwrap()); // 2^10
111+
assert!(is_power_of_two(2048).unwrap()); // 2^11
112+
assert!(is_power_of_two(4096).unwrap()); // 2^12
113+
assert!(is_power_of_two(8192).unwrap()); // 2^13
114+
assert!(is_power_of_two(16384).unwrap()); // 2^14
115+
assert!(is_power_of_two(32768).unwrap()); // 2^15
116+
assert!(is_power_of_two(65536).unwrap()); // 2^16
117+
}
118+
119+
#[test]
120+
fn test_non_powers_of_two() {
121+
assert!(!is_power_of_two(3).unwrap());
122+
assert!(!is_power_of_two(5).unwrap());
123+
assert!(!is_power_of_two(6).unwrap());
124+
assert!(!is_power_of_two(7).unwrap());
125+
assert!(!is_power_of_two(9).unwrap());
126+
assert!(!is_power_of_two(10).unwrap());
127+
assert!(!is_power_of_two(11).unwrap());
128+
assert!(!is_power_of_two(12).unwrap());
129+
assert!(!is_power_of_two(13).unwrap());
130+
assert!(!is_power_of_two(14).unwrap());
131+
assert!(!is_power_of_two(15).unwrap());
132+
assert!(!is_power_of_two(17).unwrap());
133+
assert!(!is_power_of_two(18).unwrap());
134+
}
135+
136+
#[test]
137+
fn test_specific_non_powers() {
138+
assert!(!is_power_of_two(6).unwrap());
139+
assert!(!is_power_of_two(17).unwrap());
140+
assert!(!is_power_of_two(100).unwrap());
141+
assert!(!is_power_of_two(1000).unwrap());
142+
}
143+
144+
#[test]
145+
fn test_large_powers_of_two() {
146+
assert!(is_power_of_two(131072).unwrap()); // 2^17
147+
assert!(is_power_of_two(262144).unwrap()); // 2^18
148+
assert!(is_power_of_two(524288).unwrap()); // 2^19
149+
assert!(is_power_of_two(1048576).unwrap()); // 2^20
150+
}
151+
152+
#[test]
153+
fn test_numbers_near_powers_of_two() {
154+
// One less than powers of 2
155+
assert!(!is_power_of_two(3).unwrap()); // 2^2 - 1
156+
assert!(!is_power_of_two(7).unwrap()); // 2^3 - 1
157+
assert!(!is_power_of_two(15).unwrap()); // 2^4 - 1
158+
assert!(!is_power_of_two(31).unwrap()); // 2^5 - 1
159+
assert!(!is_power_of_two(63).unwrap()); // 2^6 - 1
160+
assert!(!is_power_of_two(127).unwrap()); // 2^7 - 1
161+
assert!(!is_power_of_two(255).unwrap()); // 2^8 - 1
162+
163+
// One more than powers of 2
164+
assert!(!is_power_of_two(3).unwrap()); // 2^1 + 1
165+
assert!(!is_power_of_two(5).unwrap()); // 2^2 + 1
166+
assert!(!is_power_of_two(9).unwrap()); // 2^3 + 1
167+
assert!(!is_power_of_two(17).unwrap()); // 2^4 + 1
168+
assert!(!is_power_of_two(33).unwrap()); // 2^5 + 1
169+
assert!(!is_power_of_two(65).unwrap()); // 2^6 + 1
170+
assert!(!is_power_of_two(129).unwrap()); // 2^7 + 1
171+
}
172+
173+
#[test]
174+
fn test_negative_number_returns_error() {
175+
let result = is_power_of_two(-1);
176+
assert!(result.is_err());
177+
assert_eq!(result.unwrap_err(), "number must not be negative");
178+
}
179+
180+
#[test]
181+
fn test_multiple_negative_numbers() {
182+
assert!(is_power_of_two(-1).is_err());
183+
assert!(is_power_of_two(-2).is_err());
184+
assert!(is_power_of_two(-4).is_err());
185+
assert!(is_power_of_two(-8).is_err());
186+
assert!(is_power_of_two(-100).is_err());
187+
}
188+
189+
#[test]
190+
fn test_all_powers_of_two_up_to_30() {
191+
// Test 2^0 through 2^30
192+
for i in 0..=30 {
193+
let power = 1u32 << i; // 2^i
194+
assert!(
195+
is_power_of_two(power as i32).unwrap(),
196+
"2^{i} = {power} should be a power of 2"
197+
);
198+
}
199+
}
200+
201+
#[test]
202+
fn test_range_verification() {
203+
// Test that between consecutive powers of 2, only the powers return true
204+
for i in 1..10 {
205+
let power = 1 << i; // 2^i
206+
assert!(is_power_of_two(power).unwrap());
207+
208+
// Check numbers between this power and the next
209+
let next_power = 1 << (i + 1);
210+
for num in (power + 1)..next_power {
211+
assert!(
212+
!is_power_of_two(num).unwrap(),
213+
"{num} should not be a power of 2"
214+
);
215+
}
216+
}
217+
}
218+
219+
#[test]
220+
fn test_bit_manipulation_correctness() {
221+
// Verify the bit manipulation logic for specific examples
222+
// For 8: 1000 & 0111 = 0000 ✓
223+
assert_eq!(8 & 7, 0);
224+
assert!(is_power_of_two(8).unwrap());
225+
226+
// For 16: 10000 & 01111 = 00000 ✓
227+
assert_eq!(16 & 15, 0);
228+
assert!(is_power_of_two(16).unwrap());
229+
230+
// For 6: 110 & 101 = 100 ✗
231+
assert_ne!(6 & 5, 0);
232+
assert!(!is_power_of_two(6).unwrap());
233+
}
234+
235+
#[test]
236+
fn test_edge_case_max_i32_power_of_two() {
237+
// Largest power of 2 that fits in i32: 2^30 = 1073741824
238+
assert!(is_power_of_two(1073741824).unwrap());
239+
}
240+
}

src/bit_manipulation/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod binary_coded_decimal;
22
mod counting_bits;
33
mod find_previous_power_of_two;
44
mod highest_set_bit;
5+
mod is_power_of_two;
56
mod n_bits_gray_code;
67
mod reverse_bits;
78
mod sum_of_two_integers;
@@ -12,6 +13,7 @@ pub use self::binary_coded_decimal::binary_coded_decimal;
1213
pub use self::counting_bits::count_set_bits;
1314
pub use self::find_previous_power_of_two::find_previous_power_of_two;
1415
pub use self::highest_set_bit::find_highest_set_bit;
16+
pub use self::is_power_of_two::is_power_of_two;
1517
pub use self::n_bits_gray_code::generate_gray_code;
1618
pub use self::reverse_bits::reverse_bits;
1719
pub use self::sum_of_two_integers::add_two_integers;

0 commit comments

Comments
 (0)