Skip to content

Commit 03aaa9c

Browse files
committed
Added code to calculate twos complement of a number
1 parent db34c4b commit 03aaa9c

2 files changed

Lines changed: 114 additions & 0 deletions

File tree

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.baeldung.twoscomplement;
2+
3+
import java.math.BigInteger;
4+
5+
public class TwosComplement {
6+
7+
public static String decimalToTwosComplementBinary(BigInteger num, int numBits) {
8+
if (!canRepresentInNBits(num, numBits)) {
9+
throw new IllegalArgumentException(numBits + " bits is not enough to represent the number " + num);
10+
}
11+
var isNegative = num.signum() == -1;
12+
var absNum = num.abs();
13+
14+
// Convert the abs value of the number to its binary representation
15+
String binary = absNum.toString(2);
16+
17+
// Pad the binary representation with zeros to make it numBits long
18+
while (binary.length() < numBits) {
19+
binary = "0" + binary;
20+
}
21+
22+
// If the input number is negative, calculate two's complement
23+
if (isNegative) {
24+
binary = performTwosComplement(binary);
25+
}
26+
27+
return formatInNibbles(binary);
28+
}
29+
30+
private static String performTwosComplement(String binary) {
31+
StringBuilder result = new StringBuilder();
32+
boolean carry = true;
33+
// Perform one's complement
34+
StringBuilder onesComplement = new StringBuilder();
35+
for (int i = binary.length() - 1; i >= 0; i--) {
36+
char bit = binary.charAt(i);
37+
onesComplement.insert(0, bit == '0' ? '1' : '0');
38+
}
39+
// Addition by 1
40+
for (int i = onesComplement.length() - 1; i >= 0; i--) {
41+
char bit = onesComplement.charAt(i);
42+
if (bit == '1' && carry) {
43+
result.insert(0, '0');
44+
} else if (bit == '0' && carry) {
45+
result.insert(0, '1');
46+
carry = false;
47+
} else {
48+
result.insert(0, bit);
49+
}
50+
}
51+
52+
if (carry) {
53+
result.insert(0, '1');
54+
}
55+
56+
return result.toString();
57+
}
58+
59+
private static String formatInNibbles(String binary) {
60+
StringBuilder formattedBin = new StringBuilder();
61+
for (int i = 1; i <= binary.length(); i++) {
62+
if (i % 4 == 0 && i != binary.length()) {
63+
formattedBin.append(binary.charAt(i - 1)).append(" ");
64+
} else {
65+
formattedBin.append(binary.charAt(i - 1));
66+
}
67+
}
68+
return formattedBin.toString();
69+
}
70+
71+
private static boolean canRepresentInNBits(BigInteger number, int numBits) {
72+
BigInteger minValue = BigInteger.ONE.shiftLeft(numBits - 1).negate(); // -2^(numBits-1)
73+
BigInteger maxValue = BigInteger.ONE.shiftLeft(numBits - 1).subtract(BigInteger.ONE); // 2^(numBits-1) - 1
74+
return number.compareTo(minValue) >= 0 && number.compareTo(maxValue) <= 0;
75+
}
76+
77+
}
78+
79+
80+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.baeldung.twoscomplement;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.params.ParameterizedTest;
6+
import org.junit.jupiter.params.provider.CsvSource;
7+
8+
import java.math.BigInteger;
9+
10+
public class TwosComplementUnitTest {
11+
12+
@ParameterizedTest(name = "Twos Complement of {0} with number of bits {1}")
13+
@CsvSource({
14+
"0, 4, 0000",
15+
"1, 4, 0001",
16+
"-1, 4, 1111",
17+
"7, 4, 0111",
18+
"-7, 4, 1001",
19+
"12345, 16, 0011 0000 0011 1001",
20+
"-12345, 16, 1100 1111 1100 0111"
21+
})
22+
public void givenNumberAndBits_getTwosComplement(String number, int noOfBits, String expected) {
23+
String twosComplement = TwosComplement.decimalToTwosComplementBinary(new BigInteger(number), noOfBits);
24+
Assertions.assertEquals(expected, twosComplement);
25+
}
26+
27+
@Test
28+
public void givenNumberOutsideBitsRange_throwException() {
29+
Exception ex = Assertions.assertThrows(IllegalArgumentException.class, () -> {
30+
TwosComplement.decimalToTwosComplementBinary(BigInteger.valueOf(8), 3);
31+
});
32+
Assertions.assertEquals("3 bits is not enough to represent the number 8", ex.getMessage());
33+
}
34+
}

0 commit comments

Comments
 (0)