Дважды в шестнадцатеричную строку и обратно - PullRequest
7 голосов
/ 25 марта 2011

В Java довольно просто преобразовать двойную шестнадцатеричную строку.Но как мне сделать обратное?Мой код ниже, и я отметил, где NumberFormatException выбрасывается (примерно на 2/3 вниз).

public class HexToDoubleTest {
    public static void main( String args[] ) {

        // This is the starting double value
        double doubleInput = -9.156013e-002;

        // Convert the starting value to the equivalent value in a long
        long doubleAsLong = Double.doubleToRawLongBits( doubleInput );

        // Convert the long to a String
        String doubleAsString = Long.toHexString( doubleAsLong );

        // Print the String
        System.out.println( doubleAsString );

        // Attempt to parse the string back as a long
        // !!! This fails with a NumberFormatException !!!
        long doubleAsLongReverse = Long.parseLong( doubleAsString, 16 );

        // Convert the long back into the original double
        double doubleOutput = Double.longBitsToDouble( doubleAsLongReverse );

        // Confirm that the values match
        assert( doubleInput == doubleOutput );

    }
}

Использование Double.valueOf не удается аналогичным образом.Я уже сделал несколько поисков в Интернете и нашел несколько очень не элегантных решений.Например: использование BigInteger кажется излишним.Должен быть лучший способ!

Ответы [ 4 ]

9 голосов
/ 25 марта 2011

Почему бы не использовать методы, предоставляемые в стандартной библиотеке: Double.valueOf и Double.toHexString

Таким образом, полный пример туда и обратно будет

public static void main(String[] args){

    double doubleValue = -0.03454568;
    System.out.println("Initial double value is " + doubleValue);

    String hexStringRepresentation = Double.toHexString(doubleValue);
    System.out.println("Hex value is " + hexStringRepresentation);

    double roundtrippedDoubleValue = Double.valueOf(hexStringRepresentation);
    System.out.println("Round tripped double value is " + roundtrippedDoubleValue);
}

Nb Double.valueOf выдаст в штучной упаковке Double, а Double.parseDouble выдаст примитив double , выбрав подходящий .

или я что-то неправильно понимаю?

2 голосов
/ 17 сентября 2015

Проблема в том, что входное значение является отрицательным, и javadoc для Long.toHexString () states "Возвращает строковое представление длинного аргумента в виде целого числа без знака в базе 16. Длинное значение без знакааргумент плюс 2 ^ 64, если аргумент отрицательный; в противном случае он равен аргументу. "Однако parseLong заявляет, что "анализирует строковый аргумент как длинную со знаком в основании ..."

Так что, если у вас отрицательный ввод, то 2 ^ 64 вызывает NumberFormatException.

Если входизменено на

double doubleInput = 9.156013e-002;

преобразование работает без исключений.Чтобы справиться с отрицательным входом, требуется небольшая дополнительная обработка.

Вот класс, который показывает один способ выполнить преобразование без использования BigInteger или байтовых буферов:

public class Temp {
  public String getDoubleAsHexString(double input) {
    // Convert the starting value to the equivalent value in a long
    long doubleAsLong = Double.doubleToRawLongBits(input);
    // and then convert the long to a hex string
    return Long.toHexString(doubleAsLong);
  }

  public double convertHexStrToDouble(String input) {
    // convert the input to positive, as needed
    String s2 = preprocess(input);
    boolean negative = true;
    // if the original equals the new string, then it is not negative
    if (input.equalsIgnoreCase(s2))
      negative = false;

    // convert the hex string to long
    long doubleAsLongReverse = Long.parseLong(s2, 16);

    // Convert the long back into the original double
    double doubleOutput = Double.longBitsToDouble(doubleAsLongReverse);

    // return as a negative value, as needed
    if (negative)
      return -doubleOutput;

    return doubleOutput;
  }

  private String preprocess(String doubleAsHexString) {
    // get the first char and convert it to an int
    String s0 = doubleAsHexString.substring(0, 1);
    int int1 = Integer.parseInt(s0, 16);

    // if the int is < 8, then the string is not negative
    // and is returned without further processing
    if (int1 < 8)
      return doubleAsHexString;

    // otherwise subtract 8
    int1 = int1 - 8;
    s0 = Integer.toString(int1);

    // don't prepend a "0"
    if (int1 == 0)
      s0 = "";

    // return the string with a new inital char
    return s0 + doubleAsHexString.substring(1);
  }
}

И здесьэто тестовый класс Junit:

public class TempTest {
  private Temp t;

  @Before
  public void setUp() throws Exception {
    t = new Temp();
  }

  @Test
  public void testConvertHexStrToNegativeDouble() {
      double doubleInput = -9.156013e-002;
      String hexStr = t.getDoubleAsHexString(doubleInput);
      double doubleOutput = t.convertHexStrToDouble(hexStr);
      assertEquals(doubleInput, doubleOutput, 0.0);
    }

  @Test
  public void testConvertHexStrToPositiveDouble() {
    double doubleInput = 9.156013e-002;
    String hexStr = t.getDoubleAsHexString(doubleInput);
    double doubleOutput = t.convertHexStrToDouble(hexStr);
    assertEquals(doubleInput, doubleOutput, 0.0);
  }
}
2 голосов
/ 25 марта 2011

Вы можете разбить строку на две половины и разобрать каждую, но я думаю, что это самое простое.

long doubleAsLongReverse = new BigInteger(doubleAsString, 16).longValue();

В Java 8 теперь есть

long l = Long.parseUnsignedLong(doubleAsString, 16);

и наоборот

String s = Long.toUnsignedString(l, 16);

Они могут использоваться в сочетании с методами преобразования необработанных double в long и т. д.

0 голосов
/ 01 ноября 2012

Пример функции для обратного двойного значения:

public Double ReverseDouble( Double d) {

   byte[] bytes = new byte[8]; 
   ByteBuffer.wrap( bytes).putDouble( d); 

   for (int i=0;i<bytes.length/2;i++) {
       byte b = bytes[ i];
       bytes[ i] = bytes[ bytes.length -i -1];
       bytes[ bytes.length -i -1] = b;
   }

   return ByteBuffer.wrap( bytes).getDouble();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...