Skip to content

Commit 9da255c

Browse files
committed
refactor: Enhance docs, add more tests in TwosComplement
1 parent 2a518e3 commit 9da255c

File tree

2 files changed

+62
-31
lines changed

2 files changed

+62
-31
lines changed
Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,62 @@
11
package com.thealgorithms.bitmanipulation;
22

33
/**
4-
* @wikipedia - https://en.wikipedia.org/wiki/Two%27s_complement
5-
* This Algorithm was first suggested by Jon Von Neumann
6-
* @author - https://github.com/Monk-AbhinayVerma
7-
* @return the two's complement of any binary number
4+
* This class provides a method to compute the Two's Complement of a given binary number.
5+
*
6+
* <p>In two's complement representation, a binary number's negative value is obtained
7+
* by taking the one's complement (inverting all bits) and then adding 1 to the result.
8+
* This method handles both small and large binary strings and ensures the output is
9+
* correct for all binary inputs, including edge cases like all zeroes and all ones.
10+
*
11+
* <p>For more information on Two's Complement:
12+
* @see <a href="https://en.wikipedia.org/wiki/Two%27s_complement">Wikipedia - Two's Complement</a>
13+
*
14+
* <p>Algorithm originally suggested by Jon von Neumann.
15+
*
16+
* @author Abhinay Verma (https://github.com/Monk-AbhinayVerma)
817
*/
918
public final class TwosComplement {
1019
private TwosComplement() {
1120
}
1221

13-
// Function to get the 2's complement of a binary number
22+
/**
23+
* Computes the Two's Complement of the given binary string.
24+
* Steps:
25+
* 1. Compute the One's Complement (invert all bits).
26+
* 2. Add 1 to the One's Complement to get the Two's Complement.
27+
* 3. Iterate from the rightmost bit to the left, adding 1 and carrying over as needed.
28+
* 4. If a carry is still present after the leftmost bit, prepend '1' to handle overflow.
29+
*
30+
* @param binary The binary number as a string (only '0' and '1' characters allowed).
31+
* @return The two's complement of the input binary string as a new binary string.
32+
* @throws IllegalArgumentException If the input contains non-binary characters.
33+
*/
1434
public static String twosComplement(String binary) {
35+
if (!binary.matches("[01]+")) {
36+
throw new IllegalArgumentException("Input must contain only '0' and '1'.");
37+
}
38+
1539
StringBuilder onesComplement = new StringBuilder();
16-
// Step 1: Find the 1's complement (invert the bits)
17-
for (int i = 0; i < binary.length(); i++) {
18-
if (binary.charAt(i) == '0') {
19-
onesComplement.append('1');
20-
} else {
21-
onesComplement.append('0');
22-
}
40+
for (char bit : binary.toCharArray()) {
41+
onesComplement.append(bit == '0' ? '1' : '0');
2342
}
24-
// Step 2: Add 1 to the 1's complement
43+
2544
StringBuilder twosComplement = new StringBuilder(onesComplement);
2645
boolean carry = true;
27-
for (int i = onesComplement.length() - 1; i >= 0; i--) {
28-
if (onesComplement.charAt(i) == '1' && carry) {
46+
47+
for (int i = onesComplement.length() - 1; i >= 0 && carry; i--) {
48+
if (onesComplement.charAt(i) == '1') {
2949
twosComplement.setCharAt(i, '0');
30-
} else if (onesComplement.charAt(i) == '0' && carry) {
50+
} else {
3151
twosComplement.setCharAt(i, '1');
3252
carry = false;
3353
}
3454
}
35-
// If there is still a carry, append '1' at the beginning
55+
3656
if (carry) {
3757
twosComplement.insert(0, '1');
3858
}
59+
3960
return twosComplement.toString();
4061
}
4162
}
Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.thealgorithms.bitmanipulation;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
45

56
import org.junit.jupiter.api.Test;
67

@@ -12,7 +13,6 @@ public class TwosComplementTest {
1213

1314
@Test
1415
public void testTwosComplementAllZeroes() {
15-
// Test with a binary number consisting entirely of zeroes
1616
assertEquals("10000", TwosComplement.twosComplement("0000"));
1717
assertEquals("1000", TwosComplement.twosComplement("000"));
1818
assertEquals("100", TwosComplement.twosComplement("00"));
@@ -21,7 +21,6 @@ public void testTwosComplementAllZeroes() {
2121

2222
@Test
2323
public void testTwosComplementAllOnes() {
24-
// Test with a binary number consisting entirely of ones
2524
assertEquals("00001", TwosComplement.twosComplement("11111"));
2625
assertEquals("0001", TwosComplement.twosComplement("1111"));
2726
assertEquals("001", TwosComplement.twosComplement("111"));
@@ -30,25 +29,36 @@ public void testTwosComplementAllOnes() {
3029

3130
@Test
3231
public void testTwosComplementMixedBits() {
33-
// Test with binary numbers with mixed bits
34-
assertEquals("1111", TwosComplement.twosComplement("0001")); // 1's complement: 1110, then add 1: 1111
35-
assertEquals("1001", TwosComplement.twosComplement("0111")); // 1's complement: 1000
36-
assertEquals("11001", TwosComplement.twosComplement("00111")); // 1's complement: 11000, add 1: 11001
37-
assertEquals("011", TwosComplement.twosComplement("101")); // 1's complement: 010, add 1: 011
32+
assertEquals("1111", TwosComplement.twosComplement("0001")); // 1 -> 1111
33+
assertEquals("1001", TwosComplement.twosComplement("0111")); // 0111 -> 1001
34+
assertEquals("11001", TwosComplement.twosComplement("00111")); // 00111 -> 11001
35+
assertEquals("011", TwosComplement.twosComplement("101")); // 101 -> 011
3836
}
3937

4038
@Test
4139
public void testTwosComplementSingleBit() {
42-
// Test with single bit
43-
assertEquals("10", TwosComplement.twosComplement("0"));
44-
assertEquals("1", TwosComplement.twosComplement("1"));
40+
assertEquals("10", TwosComplement.twosComplement("0")); // 0 -> 10
41+
assertEquals("1", TwosComplement.twosComplement("1")); // 1 -> 1
4542
}
4643

4744
@Test
4845
public void testTwosComplementWithLeadingZeroes() {
49-
// Test with leading zeroes in the input
50-
assertEquals("1111", TwosComplement.twosComplement("0001"));
51-
assertEquals("101", TwosComplement.twosComplement("011"));
52-
assertEquals("110", TwosComplement.twosComplement("010"));
46+
assertEquals("1111", TwosComplement.twosComplement("0001")); // 0001 -> 1111
47+
assertEquals("101", TwosComplement.twosComplement("011")); // 011 -> 101
48+
assertEquals("110", TwosComplement.twosComplement("010")); // 010 -> 110
49+
}
50+
51+
@Test
52+
public void testInvalidBinaryInput() {
53+
// Test for invalid input that contains non-binary characters.
54+
assertThrows(IllegalArgumentException.class, () -> TwosComplement.twosComplement("102"));
55+
assertThrows(IllegalArgumentException.class, () -> TwosComplement.twosComplement("abc"));
56+
assertThrows(IllegalArgumentException.class, () -> TwosComplement.twosComplement("10a01"));
57+
}
58+
59+
@Test
60+
public void testEmptyInput() {
61+
// Edge case: Empty input should result in an IllegalArgumentException.
62+
assertThrows(IllegalArgumentException.class, () -> TwosComplement.twosComplement(""));
5363
}
5464
}

0 commit comments

Comments
 (0)