Skip to content

Commit ec96146

Browse files
Add is power of two implementation
1 parent a2225d0 commit ec96146

File tree

3 files changed

+245
-0
lines changed

3 files changed

+245
-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+
* [Highest Set Bit](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: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
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_eq!(is_power_of_two(0).unwrap(), true);
91+
}
92+
93+
#[test]
94+
fn test_one() {
95+
// 1 = 2^0
96+
assert_eq!(is_power_of_two(1).unwrap(), true);
97+
}
98+
99+
#[test]
100+
fn test_powers_of_two() {
101+
assert_eq!(is_power_of_two(2).unwrap(), true); // 2^1
102+
assert_eq!(is_power_of_two(4).unwrap(), true); // 2^2
103+
assert_eq!(is_power_of_two(8).unwrap(), true); // 2^3
104+
assert_eq!(is_power_of_two(16).unwrap(), true); // 2^4
105+
assert_eq!(is_power_of_two(32).unwrap(), true); // 2^5
106+
assert_eq!(is_power_of_two(64).unwrap(), true); // 2^6
107+
assert_eq!(is_power_of_two(128).unwrap(), true); // 2^7
108+
assert_eq!(is_power_of_two(256).unwrap(), true); // 2^8
109+
assert_eq!(is_power_of_two(512).unwrap(), true); // 2^9
110+
assert_eq!(is_power_of_two(1024).unwrap(), true); // 2^10
111+
assert_eq!(is_power_of_two(2048).unwrap(), true); // 2^11
112+
assert_eq!(is_power_of_two(4096).unwrap(), true); // 2^12
113+
assert_eq!(is_power_of_two(8192).unwrap(), true); // 2^13
114+
assert_eq!(is_power_of_two(16384).unwrap(), true); // 2^14
115+
assert_eq!(is_power_of_two(32768).unwrap(), true); // 2^15
116+
assert_eq!(is_power_of_two(65536).unwrap(), true); // 2^16
117+
}
118+
119+
#[test]
120+
fn test_non_powers_of_two() {
121+
assert_eq!(is_power_of_two(3).unwrap(), false);
122+
assert_eq!(is_power_of_two(5).unwrap(), false);
123+
assert_eq!(is_power_of_two(6).unwrap(), false);
124+
assert_eq!(is_power_of_two(7).unwrap(), false);
125+
assert_eq!(is_power_of_two(9).unwrap(), false);
126+
assert_eq!(is_power_of_two(10).unwrap(), false);
127+
assert_eq!(is_power_of_two(11).unwrap(), false);
128+
assert_eq!(is_power_of_two(12).unwrap(), false);
129+
assert_eq!(is_power_of_two(13).unwrap(), false);
130+
assert_eq!(is_power_of_two(14).unwrap(), false);
131+
assert_eq!(is_power_of_two(15).unwrap(), false);
132+
assert_eq!(is_power_of_two(17).unwrap(), false);
133+
assert_eq!(is_power_of_two(18).unwrap(), false);
134+
}
135+
136+
#[test]
137+
fn test_specific_non_powers() {
138+
assert_eq!(is_power_of_two(6).unwrap(), false);
139+
assert_eq!(is_power_of_two(17).unwrap(), false);
140+
assert_eq!(is_power_of_two(100).unwrap(), false);
141+
assert_eq!(is_power_of_two(1000).unwrap(), false);
142+
}
143+
144+
#[test]
145+
fn test_large_powers_of_two() {
146+
assert_eq!(is_power_of_two(131072).unwrap(), true); // 2^17
147+
assert_eq!(is_power_of_two(262144).unwrap(), true); // 2^18
148+
assert_eq!(is_power_of_two(524288).unwrap(), true); // 2^19
149+
assert_eq!(is_power_of_two(1048576).unwrap(), true); // 2^20
150+
}
151+
152+
#[test]
153+
fn test_numbers_near_powers_of_two() {
154+
// One less than powers of 2
155+
assert_eq!(is_power_of_two(3).unwrap(), false); // 2^2 - 1
156+
assert_eq!(is_power_of_two(7).unwrap(), false); // 2^3 - 1
157+
assert_eq!(is_power_of_two(15).unwrap(), false); // 2^4 - 1
158+
assert_eq!(is_power_of_two(31).unwrap(), false); // 2^5 - 1
159+
assert_eq!(is_power_of_two(63).unwrap(), false); // 2^6 - 1
160+
assert_eq!(is_power_of_two(127).unwrap(), false); // 2^7 - 1
161+
assert_eq!(is_power_of_two(255).unwrap(), false); // 2^8 - 1
162+
163+
// One more than powers of 2
164+
assert_eq!(is_power_of_two(3).unwrap(), false); // 2^1 + 1
165+
assert_eq!(is_power_of_two(5).unwrap(), false); // 2^2 + 1
166+
assert_eq!(is_power_of_two(9).unwrap(), false); // 2^3 + 1
167+
assert_eq!(is_power_of_two(17).unwrap(), false); // 2^4 + 1
168+
assert_eq!(is_power_of_two(33).unwrap(), false); // 2^5 + 1
169+
assert_eq!(is_power_of_two(65).unwrap(), false); // 2^6 + 1
170+
assert_eq!(is_power_of_two(129).unwrap(), false); // 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_eq!(
195+
is_power_of_two(power as i32).unwrap(),
196+
true,
197+
"2^{i} = {power} should be a power of 2"
198+
);
199+
}
200+
}
201+
202+
#[test]
203+
fn test_range_verification() {
204+
// Test that between consecutive powers of 2, only the powers return true
205+
for i in 1..10 {
206+
let power = 1 << i; // 2^i
207+
assert_eq!(is_power_of_two(power).unwrap(), true);
208+
209+
// Check numbers between this power and the next
210+
let next_power = 1 << (i + 1);
211+
for num in (power + 1)..next_power {
212+
assert_eq!(
213+
is_power_of_two(num).unwrap(),
214+
false,
215+
"{num} should not be a power of 2"
216+
);
217+
}
218+
}
219+
}
220+
221+
#[test]
222+
fn test_bit_manipulation_correctness() {
223+
// Verify the bit manipulation logic for specific examples
224+
// For 8: 1000 & 0111 = 0000 ✓
225+
assert_eq!(8 & 7, 0);
226+
assert_eq!(is_power_of_two(8).unwrap(), true);
227+
228+
// For 16: 10000 & 01111 = 00000 ✓
229+
assert_eq!(16 & 15, 0);
230+
assert_eq!(is_power_of_two(16).unwrap(), true);
231+
232+
// For 6: 110 & 101 = 100 ✗
233+
assert_ne!(6 & 5, 0);
234+
assert_eq!(is_power_of_two(6).unwrap(), false);
235+
}
236+
237+
#[test]
238+
fn test_edge_case_max_i32_power_of_two() {
239+
// Largest power of 2 that fits in i32: 2^30 = 1073741824
240+
assert_eq!(is_power_of_two(1073741824).unwrap(), true);
241+
}
242+
}

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)