Quick Background for this.
I am writing a Site.com page to gather client Data for configuring of routers. I currently ask users to enter there internal IP Address and Submask.
I then work out the IP Ranger. I believe to do this requires Binary Conversations and Addition.
I have everything working well apart from the Binary Addition.
I have written a full adder and half adder however my results come out as "011111111111111111111111111111111"
can anyone see what i've done wrong?
PS, All Conversation are working correctly to get the first Available Address. It is the LAST address I am having an issue with.
private static String binaryAddition(List<String> aInput, List<String> bInput)
{
String a = '';
for(String s : aInput)
a = a + s;
String b = '';
for(String s : bInput)
b = b + s;
String sum = '';
String carry = '';
for(Integer i = a.length() -1; i>=0; i-- )
{
if( i == a.length() - 1)
{
Adder halfAdd1 = halfAdder(a.substring(i, i+1),b.substring(i, i+1));
sum = halfAdd1.sum + sum;
carry = halfAdd1.carry;
}
else
{
Adder fullAdd = fullAdder(a.substring(i, i+1),b.substring(i, i+1), carry);
sum = fullAdd.sum+sum;
carry = fullAdd.carry;
}
}
return (carry.equals('0') ? carry + sum : sum );
}
private static Adder fullAdder(String a, String b, String carry)
{
Adder halfAdd = halfAdder(a,b);
string sum = xorOp(carry, halfAdd.sum);
carry = andOp(carry, halfAdd.sum);
//carry += orOp(carry, halfAdd.carry);
Adder result = new Adder();
result.sum = sum;
result.carry = carry;
return result;
}
private static Adder halfAdder(String a, String b)
{
string sum = xorOp(a,b);
string carry = andOp(a,b);
Adder result = new Adder();
result.sum = sum;
result.carry = carry;
return result;
}
private static String xorOp(String a, String b)
{
return (a == b ? '0' : '1');
}
private static String andOp (String a, String b)
{
return a == '1' && b == '1' ? '1' : '0';
}
private static String orOp(String a, String b)
{
return a;
}
public class Adder
{
String sum;
String carry;
}
Best Answer
Breaking down an IPv4 address (and the netmask) to a binary string, implementing 1-bit adders, and then converting back to an IPv4 address seems to me to be doing things the hard way.
Granted, there really isn't an 'easy' way to go about manipulating IP addresses, but the route that I chose to go down when I implemented a set of IP Address utility methods (it was one of my first big projects as a professional developer, when script statement limits in Apex were still a thing) was to work in integers as much as possible.
I might go about it slightly differently if I were to re-implement things today, but the starting point I used was to convert an IPv4 address, represented in dot-decimal notation as a string, to a
List<Integer>
.That bit is simple enough.
Once both the given IPv4 address and the netmask are integer lists, getting the first address in the range is as simple as stepping through each octet (of both the IPv4 address, and the netmask), and performing a bitwise-and.
The last address in a range is a bit trickier. It's the bitwise-or of the given ip address together with the inverse of the netmask. There isn't a bitwise-not that I'm aware of, so we'll need to implement
invert()
ourselves. Luckily, it's easy enough.Now that we have our
invert()
method, we can find the last address in a rangeFrom here, you could add handling for IPv6 without too much trouble. The algorithms for finding the first and last addresses in the range remain the same. The
invert
method would simply need to have255
replaced with65535
. The biggest pain, really, would be that you need to convert from hexadecimal to decimal (and then back again when you wanted to display the resulting IPv6 address).If you need anything other than the first and last addresses in a range, then implementing
add()
andsubtract()
methods would be helpful. I won't provide an implementation of those (unless asked), but the algorithm is simple enough.Subtracting is nothing more than adding a negative, but you'd need to change the logic a bit to support borrowing from greater octets.