2013-04-25 4 views
1

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

String test = "fffff8000261e000" 
long number = Long.parseLong(test, 16); 

Это проливает NumberFormatException:

java.lang.NumberFormatException: For input string: "fffff8000261e000" 

Однако, если я выбиваю первую «f» из строки, она разбирает ее в порядке.

Я предполагаю, что это потому, что число велико, и то, что я обычно делаю, это положить «L» на конец долгого, чтобы исправить эту проблему. Я не могу, однако, разработать лучший способ сделать это при синтаксическом анализе длинной строки.

Может ли кто-нибудь предложить какие-либо советы?

Благодаря

+0

обратите внимание: http://stackoverflow.com/questions/849813/large-numbers-in-java – wemu

+0

Проверьте 'BigDecimal', он должен быть в состоянии обрабатывать большие , точные числа не проблема. http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html – Kyle

+2

Если, как вы правильно заметили, число слишком велико, вы не сможете разобрать длинные , Вам понадобится числовой тип с более высокой пропускной способностью. Как указывает @wemu, попробуйте разобрать его в «BigInteger». Если вам по-прежнему нужен «длинный», попробуйте использовать «BigInteger # longValue()». – Gamb

ответ

4

Существует два разных способа ответа на ваш вопрос, в зависимости от того, какое поведение вы действительно ищете.

Ответ # 1: Как и другие люди указали, ваша строка (интерпретируются как положительного шестнадцатеричного целое) является слишком большой для типа Java long. Поэтому, если вам действительно нужны (положительные) целые числа, большие, тогда вам нужно будет использовать другой тип, возможно, java.math.BigInteger, который также имеет конструктор с String и основанием.

Ответ # 2: Интересно, однако, если ваша строка представляет «необработанные» байты long. В вашем примере это будет отрицательное число. Если это так, то встроенный в Java анализатор long не обрабатывает значения, где установлен высокий бит (т. Е. Где первая цифра 16-разрядной строки больше 7).

Если вы в случае # 2, то здесь один (довольно неэффективный) способ его обработки:

String test = "fffff8000261e000"; 
long number = new java.math.BigInteger(test, 16).longValue(); 

, которая производит значение -8796053053440. (Если ваша строка имеет длину более 16 шестнадцатеричных цифр, она будет автоматически отбрасывать любые более высокие разряды.)

Если эффективность представляет собой проблему, вы можете написать свою собственную процедуру битового кручения, которая принимает шестнадцатеричные цифры с конца строка два за раз, возможно, построение массива байтов, а затем преобразование в длинное. Похожий код здесь:

How to convert a Java Long to byte[] for Cassandra?

1

Число вы разборе слишком большой, чтобы поместиться в Java Long. Добавление L не помогло бы. Если Long был неподписанным типом данных, он бы соответствовал.

Один из способов справиться это разделить строку на две части, а затем использовать битовую сдвиг при добавлении их вместе:

String s= "fffff8000261e000"; 
long number; 
long n1, n2; 

if (s.length() < 16) { 
    number = Long.parseLong(s, 16); 
} 
else { 
    String s1 = s.substring(0, 1); 
    String s2 = s.substring(1, s.length()); 

    n1=Long.parseLong(s1, 16) << (4 * s2.length()); 
    n2= Long.parseLong(s2, 16); 

    number = (Long.parseLong(s1, 16) << (4 * s2.length())) + Long.parseLong(s2, 16); 
    System.out.println(Long.toHexString(n1)); 
    System.out.println(Long.toHexString(n2)); 
    System.out.println(Long.toHexString(number)); 
} 

Примечание:

Если число больше, чем Long.MAX_VALUE результирующая long будет отрицательным значением, но бит-шаблон будет соответствовать входу.

+0

Я не думаю, что это может вернуть правильный ответ? –

+1

Мой тест показывает, что Long.toHexString (number) - f00000000000000. –

+0

@ Ziyao Wei В моем коде была ошибка (присвоение 's2' было отключено одним). Обновленный код протестирован и работает. Спасибо, что указал на ошибку. –

1

Переменная может содержать значения в диапазоне от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807 включительно.

Расчет показывает, что fffff8000261e000 hexademical является 18,446,735,277,656,498,176 десятичным, что явно выходит за пределы. Вместо этого, fffff8000261e000 hexademical - это 1,152,912,708,553,793,536 десятичный знак, который, как очевидно, находится в пределах.

Как и все здесь, используйте BigInteger для учета таких случаев. Например, BigInteger bi = new BigInteger("fffff8000261e000", 16); решит вашу проблему. Кроме того, new java.math.BigInteger("fffff8000261e000", 16).toString() точно даст 18446735277656498176.

+0

Интересно, но это не отвечает на вопрос. Это скорее подходит для комментариев, если вы не предложите решение. – Gamb