Как я могу преобразовать long в его двоичное 32-битное представление? - PullRequest
0 голосов
/ 15 марта 2020

Я выполняю следующее упражнение по программированию: int32 to IPv4 . Это утверждение:

Примите следующий адрес IPv4: 128.32.10.1

Этот адрес имеет 4 октета, где каждый октет представляет собой один байт (или 8 бит).

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

Итак 128.32.10.1 == 10000000.00100000.00001010.00000001

Поскольку указанный IP-адрес имеет 32 бита, мы можем представить его как 32-разрядное число без знака: 2149583361

Завершить функцию он принимает 32-разрядное число без знака и возвращает строковое представление своего адреса IPv4. Примеры

2149583361 ==> "128.32.10.1" 32 ==> "0.0.0.32" 0 ==> "0.0.0.0"

Сначала я попробовал следующий код :

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));
    }
}

И будучи тестами:

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));
    }
}

Когда ввод равен нулю, мой код выдает исключение: java.lang.StringIndexOutOfBoundsException: begin 0, end 8, length 1 at Kata.longToIP(Kata.java:6)

Из-за строки 4, где я конвертирую из long в строку, двоичный файл не имеет нулевых полей:

ip: 0
binary: 0

Как я могу преобразовать значение long ip в двоичную строку с всегда 32 цифрами (с добавлением отступа 0)?

Я попробовал следующий подход:

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));
    }
}

И он выдает java.lang.NumberFormatException: For input string: "10000000011100100001000101101000" at Kata.longToIP(Kata.java:4)

Затем я изменил его на:

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));
    }
}

И это также вызывает исключение:

java.lang.NumberFormatException: For input string: "00000021"
at Kata.longToIP(Kata.java:7)

Я прочитал:

Ответы [ 4 ]

2 голосов
/ 15 марта 2020
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;
    }
}
0 голосов
/ 15 марта 2020

Для преобразования значения int в стандартный формат четырехточечных точек это будет работать. Просто сдвиньте значения слева, уменьшив значения до 8 и добавив соответствующие строки.

    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;
    }

Чтобы преобразовать int в двоичное значение с дополни тельной длиной 32, попробуйте следующее. Это гарантирует, что переданное int преобразуется в 33-битное значение, поэтому стандартный метод Long.toBinaryString вернет 33-символьное значение. Первый символ брошен, поскольку он выполнил свою задачу.

    public static String toPaddedBinary(int v) {
        long x = (v|(1L<<32))&0x1FFFFFFFFL;
        return Long.toBinaryString(x).substring(1);
    }

Следующий код показывает вывод.

        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();
        }

Печать

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



0 голосов
/ 15 марта 2020

Как можно преобразовать длинное значение ip в двоичную строку с всегда 32 цифрами (с добавлением отступа 0)?

Ниже приведен пример печати int в 32 -битное представление:

public class Main {
    public static void main(String[] argv) throws Exception {
        // Convert 20 to binary and print it in 32-bit form with left-padded 0s
        System.out.println(String.format("%32s", Integer.toBinaryString(20)).replace(' ', '0'));
    }
}

Вывод:

00000000000000000000000000010100
0 голосов
/ 15 марта 2020

Мы могли бы добавить нули заполнения:

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));
    }
}

Или мы могли бы сделать это в том же предложении, где мы конвертируем из длинной в двоичную строку, используя формат (основанный на Джефф Скотт Браун ответ на этот топи c Преобразование long в двоичное в Java дает 31 бит? :

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));
    }
}

Кроме того, мы могли бы использовать библиотеки net java ( Angelwrith решение):

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;
        }
    }
}
...