Reputation: 2134
I am doing the following programming exercise: int32 to IPv4. The statement is:
Take the following IPv4 address: 128.32.10.1
This address has 4 octets where each octet is a single byte (or 8 bits).
1st octet 128 has the binary representation: 10000000 2nd octet 32 has the binary representation: 00100000 3rd octet 10 has the binary representation: 00001010 4th octet 1 has the binary representation: 00000001
So 128.32.10.1 == 10000000.00100000.00001010.00000001
Because the above IP address has 32 bits, we can represent it as the unsigned 32 bit number: 2149583361
Complete the function that takes an unsigned 32 bit number and returns a string representation of its IPv4 address. Examples
2149583361 ==> "128.32.10.1" 32 ==> "0.0.0.32" 0 ==> "0.0.0.0"
First, I tried the following code:
public class Kata {
public static String longToIP(long ip) {
System.out.println("ip: "+ip);
String binary = Long.toBinaryString(ip);
System.out.println("binary: "+binary);
return String.format("%s.%s.%s.%s",Long.parseLong(binary.substring(0,8),2),Long.parseLong(binary.substring(8,16),2),
Long.parseLong(binary.substring(16,24),2),Long.parseLong(binary.substring(24),2));
}
}
And being the tests:
import org.junit.Test;
import java.util.Random;
import static org.junit.Assert.assertEquals;
public class KataTest {
@Test
public void sampleTest() {
assertEquals("128.114.17.104", Kata.longToIP(2154959208L));
assertEquals("0.0.0.0", Kata.longToIP(0));
assertEquals("128.32.10.1", Kata.longToIP(2149583361L));
}
}
When input is zero, my code throws an exception: java.lang.StringIndexOutOfBoundsException: begin 0, end 8, length 1
at Kata.longToIP(Kata.java:6)
Because of at line 4, where I convert from long to string, binary has not padding zeros:
ip: 0
binary: 0
How could I cast the long ip value to a binary string with always 32 digits (adding padding 0)?
I tried the following approach:
public class Kata {
public static String longToIP(long ip) {
System.out.println("ip: "+ip);
String binary = String.format("%032d",Long.parseLong(Long.toBinaryString(ip)));
System.out.println("binary: "+binary);
return String.format("%s.%s.%s.%s",Long.parseLong(binary.substring(0,8),2),Long.parseLong(binary.substring(8,16),2),
Long.parseLong(binary.substring(16,24),2),Long.parseLong(binary.substring(24),2));
}
}
And it throws java.lang.NumberFormatException: For input string: "10000000011100100001000101101000" at Kata.longToIP(Kata.java:4)
Then I changed it to:
public class Kata {
public static String longToIP(long ip) {
System.out.println("ip: "+ip);
String binary = String.format("%032d",Long.parseLong(Long.toBinaryString(ip),2));
System.out.println("binary: "+binary);
return String.format("%s.%s.%s.%s",Long.parseLong(binary.substring(0,8),2),Long.parseLong(binary.substring(8,16),2),
Long.parseLong(binary.substring(16,24),2),Long.parseLong(binary.substring(24),2));
}
}
And this also throws an exception:
java.lang.NumberFormatException: For input string: "00000021"
at Kata.longToIP(Kata.java:7)
I have read:
Upvotes: 0
Views: 2712
Reputation: 40057
To convert an int value to the standard dotted quad format, this will work. It is a simple matter of shifting the values from the left by decreasing values of 8 and appending the appropriate strings.
public static String toIP(int x) {
String ip = Integer.toString((int) (x >> 24 & 0xFF)) + ".";
ip += Integer.toString((int) ((x >> 16) & 0xFF)) + ".";
ip += Integer.toString((int) ((x >> 8) & 0xFF)) + ".";
ip += Integer.toString((int) (x & 0xFF));
return ip;
}
To convert an int to a padded binary value of length 32, try the following. It ensures that the passed int is converted to a 33 bit value so the standard Long.toBinaryString
method will return a 33 character value. The first character is tossed since it has served its purpose.
public static String toPaddedBinary(int v) {
long x = (v|(1L<<32))&0x1FFFFFFFFL;
return Long.toBinaryString(x).substring(1);
}
The following code shows the output.
int [] data = {32, 1233, Integer.MAX_VALUE, Integer.MIN_VALUE, 192<<24|156<<16|5};
for (int d : data) {
System.out.println(toIP(d));
System.out.println(toPaddedBinary(d));
System.out.println();
}
Prints
0.0.0.32
00000000000000000000000000100000
0.0.4.209
00000000000000000000010011010001
127.255.255.255
01111111111111111111111111111111
128.0.0.0
10000000000000000000000000000000
192.156.0.5
11000000100111000000000000000101
Upvotes: 0
Reputation: 1071
public class Kata {
public static String longToIP(long ip) {
//1. translate the ip to binary representation
String str = "";
if (ip == 0) {
str = ip + "";
} else {
while (ip != 0) {
str = ip % 2 + str;
ip = ip / 2;
}
}
//2. if the binary string is shorter than 32 bit, then add "0" in front
while (str.length() != 32) {
str = "0" + str;
}
String result = "";
//3. truncate the str to four items
for (int i = 0; i < 4; i++) {
String partStr = str.substring(i * 8, 8 * (i + 1));
//4. translate every item to decimal number
int bi = Integer.parseInt(partStr, 2);
if (i == 3) {
result += bi + "";
} else {
result += bi + ".";
}
}
return result;
}
}
Upvotes: 2
Reputation: 2134
We could add padding zeros:
public class Kata {
public static String longToIP(long ip) {
System.out.println("ip: "+ip);
String binary = Long.toBinaryString(ip);
if(binary.length()<32) binary = "0".repeat(32-binary.length()) + binary;
System.out.println("binary: "+binary);
return String.format("%s.%s.%s.%s",Long.parseLong(binary.substring(0,8),2),Long.parseLong(binary.substring(8,16),2),
Long.parseLong(binary.substring(16,24),2),Long.parseLong(binary.substring(24),2));
}
}
Or, we could do it in the same sentence where we convert from long to binary string, using format (based on Jeff Scott Brown answer to this topic Converting long to binary in Java gives 31 bits?:
public class Kata {
public static String longToIP(long ip) {
System.out.println("ip: "+ip);
String binary = String.format("%32s",Long.toBinaryString(ip)).replace(' ','0');
System.out.println("binary: "+binary);
return String.format("%s.%s.%s.%s",Long.parseLong(binary.substring(0,8),2),Long.parseLong(binary.substring(8,16),2),
Long.parseLong(binary.substring(16,24),2),Long.parseLong(binary.substring(24),2));
}
}
In addition we could use net java libraries (Angelwrith solution):
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Kata {
public static String longToIP(long ip) {
try {
return InetAddress.getByName(String.valueOf(ip)).getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
return null;
}
}
}
Upvotes: 0