Yone
Yone

Reputation: 2134

How can I convert a long to its binary 32 bit representation?

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

Answers (3)

WJS
WJS

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

Alessandro Candeloro
Alessandro Candeloro

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

Yone
Yone

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

Related Questions