Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e5bceac

Browse files
Add two's complement implementation (TheAlgorithms#968)
1 parent 00cbbb9 commit e5bceac

File tree

3 files changed

+147
-7
lines changed

3 files changed

+147
-7
lines changed

‎DIRECTORY.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* [Reverse Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/reverse_bits.rs)
2525
* [Sum of Two Integers](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/sum_of_two_integers.rs)
2626
* [Swap Odd and Even Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/swap_odd_even_bits.rs)
27+
* [Two's Complement](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/twos_complement.rs)
2728
* Ciphers
2829
* [AES](https://github.com/TheAlgorithms/Rust/blob/master/src/ciphers/aes.rs)
2930
* [Another ROT13](https://github.com/TheAlgorithms/Rust/blob/master/src/ciphers/another_rot13.rs)

‎src/bit_manipulation/mod.rs‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ mod n_bits_gray_code;
55
mod reverse_bits;
66
mod sum_of_two_integers;
77
mod swap_odd_even_bits;
8+
mod twos_complement;
89

9-
pub use binary_coded_decimal::binary_coded_decimal;
10-
pub use counting_bits::count_set_bits;
11-
pub use highest_set_bit::find_highest_set_bit;
12-
pub use n_bits_gray_code::generate_gray_code;
13-
pub use reverse_bits::reverse_bits;
14-
pub use sum_of_two_integers::add_two_integers;
15-
pub use swap_odd_even_bits::swap_odd_even_bits;
10+
pub use self::binary_coded_decimal::binary_coded_decimal;
11+
pub use self::counting_bits::count_set_bits;
12+
pub use self::highest_set_bit::find_highest_set_bit;
13+
pub use self::n_bits_gray_code::generate_gray_code;
14+
pub use self::reverse_bits::reverse_bits;
15+
pub use self::sum_of_two_integers::add_two_integers;
16+
pub use self::swap_odd_even_bits::swap_odd_even_bits;
17+
pub use self::twos_complement::twos_complement;
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
//! Two's Complement Representation
2+
//!
3+
//! Two's complement is a mathematical operation on binary numbers and a binary signed
4+
//! number representation. It is widely used in computing as the most common method of
5+
//! representing signed integers on computers.
6+
//!
7+
//! For more information: <https://en.wikipedia.org/wiki/Two%27s_complement>
8+
9+
/// Takes a negative integer and returns its two's complement binary representation.
10+
///
11+
/// The two's complement of a negative number is calculated by finding the binary
12+
/// representation that, when added to the positive value with the same magnitude,
13+
/// equals 2^n (where n is the number of bits).
14+
///
15+
/// # Arguments
16+
///
17+
/// * `number` - A non-positive integer (0 or negative)
18+
///
19+
/// # Returns
20+
///
21+
/// A `Result` containing:
22+
/// - `Ok(String)` - The two's complement representation with "0b" prefix
23+
/// - `Err(String)` - An error message if the input is positive
24+
///
25+
/// # Examples
26+
///
27+
/// ```
28+
/// use the_algorithms_rust::bit_manipulation::twos_complement;
29+
///
30+
/// assert_eq!(twos_complement(0).unwrap(), "0b0");
31+
/// assert_eq!(twos_complement(-1).unwrap(), "0b11");
32+
/// assert_eq!(twos_complement(-5).unwrap(), "0b1011");
33+
/// assert_eq!(twos_complement(-17).unwrap(), "0b101111");
34+
/// assert_eq!(twos_complement(-207).unwrap(), "0b100110001");
35+
///
36+
/// // Positive numbers return an error
37+
/// assert!(twos_complement(1).is_err());
38+
/// ```
39+
///
40+
/// # Errors
41+
///
42+
/// Returns an error if the input number is positive.
43+
pub fn twos_complement(number: i32) -> Result<String, String> {
44+
if number > 0 {
45+
return Err("input must be a negative integer".to_string());
46+
}
47+
48+
if number == 0 {
49+
return Ok("0b0".to_string());
50+
}
51+
52+
// Calculate the number of bits needed for the binary representation
53+
// (excluding the sign bit in the original representation)
54+
let binary_number_length = format!("{:b}", number.abs()).len();
55+
56+
// Calculate two's complement value
57+
// This is equivalent to: abs(number) - 2^binary_number_length
58+
let twos_complement_value = (number.abs() as i64) - (1_i64 << binary_number_length);
59+
60+
// Format as binary string (removing the negative sign)
61+
let mut twos_complement_str = format!("{:b}", twos_complement_value.abs());
62+
63+
// Add leading zeros if necessary
64+
let padding_zeros = binary_number_length.saturating_sub(twos_complement_str.len());
65+
if padding_zeros > 0 {
66+
twos_complement_str = format!("{}{twos_complement_str}", "0".repeat(padding_zeros));
67+
}
68+
69+
// Add leading '1' to indicate negative number in two's complement
70+
Ok(format!("0b1{twos_complement_str}"))
71+
}
72+
73+
#[cfg(test)]
74+
mod tests {
75+
use super::*;
76+
77+
#[test]
78+
fn test_zero() {
79+
assert_eq!(twos_complement(0).unwrap(), "0b0");
80+
}
81+
82+
#[test]
83+
fn test_negative_one() {
84+
assert_eq!(twos_complement(-1).unwrap(), "0b11");
85+
}
86+
87+
#[test]
88+
fn test_negative_five() {
89+
assert_eq!(twos_complement(-5).unwrap(), "0b1011");
90+
}
91+
92+
#[test]
93+
fn test_negative_seventeen() {
94+
assert_eq!(twos_complement(-17).unwrap(), "0b101111");
95+
}
96+
97+
#[test]
98+
fn test_negative_two_hundred_seven() {
99+
assert_eq!(twos_complement(-207).unwrap(), "0b100110001");
100+
}
101+
102+
#[test]
103+
fn test_negative_small_values() {
104+
assert_eq!(twos_complement(-2).unwrap(), "0b110");
105+
assert_eq!(twos_complement(-3).unwrap(), "0b101");
106+
assert_eq!(twos_complement(-4).unwrap(), "0b1100");
107+
}
108+
109+
#[test]
110+
fn test_negative_larger_values() {
111+
assert_eq!(twos_complement(-128).unwrap(), "0b110000000");
112+
assert_eq!(twos_complement(-255).unwrap(), "0b100000001");
113+
assert_eq!(twos_complement(-1000).unwrap(), "0b10000011000");
114+
}
115+
116+
#[test]
117+
fn test_positive_number_returns_error() {
118+
let result = twos_complement(1);
119+
assert!(result.is_err());
120+
assert_eq!(result.unwrap_err(), "input must be a negative integer");
121+
}
122+
123+
#[test]
124+
fn test_large_positive_number_returns_error() {
125+
let result = twos_complement(100);
126+
assert!(result.is_err());
127+
assert_eq!(result.unwrap_err(), "input must be a negative integer");
128+
}
129+
130+
#[test]
131+
fn test_edge_case_negative_powers_of_two() {
132+
assert_eq!(twos_complement(-8).unwrap(), "0b11000");
133+
assert_eq!(twos_complement(-16).unwrap(), "0b110000");
134+
assert_eq!(twos_complement(-32).unwrap(), "0b1100000");
135+
assert_eq!(twos_complement(-64).unwrap(), "0b11000000");
136+
}
137+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /