Added code to calculate twos complement of a number
This commit is contained in:
parent
db34c4b3c3
commit
03aaa9ceeb
@ -0,0 +1,80 @@
|
|||||||
|
package com.baeldung.twoscomplement;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class TwosComplement {
|
||||||
|
|
||||||
|
public static String decimalToTwosComplementBinary(BigInteger num, int numBits) {
|
||||||
|
if (!canRepresentInNBits(num, numBits)) {
|
||||||
|
throw new IllegalArgumentException(numBits + " bits is not enough to represent the number " + num);
|
||||||
|
}
|
||||||
|
var isNegative = num.signum() == -1;
|
||||||
|
var absNum = num.abs();
|
||||||
|
|
||||||
|
// Convert the abs value of the number to its binary representation
|
||||||
|
String binary = absNum.toString(2);
|
||||||
|
|
||||||
|
// Pad the binary representation with zeros to make it numBits long
|
||||||
|
while (binary.length() < numBits) {
|
||||||
|
binary = "0" + binary;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the input number is negative, calculate two's complement
|
||||||
|
if (isNegative) {
|
||||||
|
binary = performTwosComplement(binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatInNibbles(binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String performTwosComplement(String binary) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
boolean carry = true;
|
||||||
|
// Perform one's complement
|
||||||
|
StringBuilder onesComplement = new StringBuilder();
|
||||||
|
for (int i = binary.length() - 1; i >= 0; i--) {
|
||||||
|
char bit = binary.charAt(i);
|
||||||
|
onesComplement.insert(0, bit == '0' ? '1' : '0');
|
||||||
|
}
|
||||||
|
// Addition by 1
|
||||||
|
for (int i = onesComplement.length() - 1; i >= 0; i--) {
|
||||||
|
char bit = onesComplement.charAt(i);
|
||||||
|
if (bit == '1' && carry) {
|
||||||
|
result.insert(0, '0');
|
||||||
|
} else if (bit == '0' && carry) {
|
||||||
|
result.insert(0, '1');
|
||||||
|
carry = false;
|
||||||
|
} else {
|
||||||
|
result.insert(0, bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (carry) {
|
||||||
|
result.insert(0, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatInNibbles(String binary) {
|
||||||
|
StringBuilder formattedBin = new StringBuilder();
|
||||||
|
for (int i = 1; i <= binary.length(); i++) {
|
||||||
|
if (i % 4 == 0 && i != binary.length()) {
|
||||||
|
formattedBin.append(binary.charAt(i - 1)).append(" ");
|
||||||
|
} else {
|
||||||
|
formattedBin.append(binary.charAt(i - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formattedBin.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean canRepresentInNBits(BigInteger number, int numBits) {
|
||||||
|
BigInteger minValue = BigInteger.ONE.shiftLeft(numBits - 1).negate(); // -2^(numBits-1)
|
||||||
|
BigInteger maxValue = BigInteger.ONE.shiftLeft(numBits - 1).subtract(BigInteger.ONE); // 2^(numBits-1) - 1
|
||||||
|
return number.compareTo(minValue) >= 0 && number.compareTo(maxValue) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.baeldung.twoscomplement;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class TwosComplementUnitTest {
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "Twos Complement of {0} with number of bits {1}")
|
||||||
|
@CsvSource({
|
||||||
|
"0, 4, 0000",
|
||||||
|
"1, 4, 0001",
|
||||||
|
"-1, 4, 1111",
|
||||||
|
"7, 4, 0111",
|
||||||
|
"-7, 4, 1001",
|
||||||
|
"12345, 16, 0011 0000 0011 1001",
|
||||||
|
"-12345, 16, 1100 1111 1100 0111"
|
||||||
|
})
|
||||||
|
public void givenNumberAndBits_getTwosComplement(String number, int noOfBits, String expected) {
|
||||||
|
String twosComplement = TwosComplement.decimalToTwosComplementBinary(new BigInteger(number), noOfBits);
|
||||||
|
Assertions.assertEquals(expected, twosComplement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNumberOutsideBitsRange_throwException() {
|
||||||
|
Exception ex = Assertions.assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
TwosComplement.decimalToTwosComplementBinary(BigInteger.valueOf(8), 3);
|
||||||
|
});
|
||||||
|
Assertions.assertEquals("3 bits is not enough to represent the number 8", ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user