2013-04-25 63 views
1

我目前正试图解析作为字符串存储在Java中一些长期价值解析长,我的问题是这样的:从Java字符串

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

这将引发一个NumberFormatException异常:

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

但是,如果我敲掉字符串中的第一个'f',它会很好地解析它。

我猜这是因为这个数字很大,我通常会做的是在长的末尾放一个'L'来解决这个问题。然而,当我从字符串中解析一个long时,我无法找到解决这个问题的最佳方法。

任何人都可以提供任何建议吗?

谢谢

+0

请注意:http://stackoverflow.com/questions/849813/large-numbers-in-java – wemu 2013-04-25 14:07:53

+0

退房'BigDecimal',它应该能够处理大型,确切的数字没有问题。 http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html – Kyle 2013-04-25 14:13:37

+2

如果您正确地发现该数字太大,您将无法解析长时间。你需要一个容量更大的数字类型。正如@wemu指出的那样,尝试将它解析为一个BigInteger。如果你仍然需要使用'BigInteger#longValue()'进行'长'尝试。 – Gamb 2013-04-25 14:13:54

回答

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位十六进制数字,它会自动丢弃任何高位)。

如果效率是一个问题,你可以编写自己的位扭曲程序,它将十六进制数字从一次两个字符串,也许建立一个字节数组,然后转换为long。一些类似的代码是在这里:

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

我不认为这可以返回正确的答案? – 2013-04-25 14:15:06

+1

我的测试显示Long.toHexString(number)是f00000000000000。 – 2013-04-25 14:17:48

+0

@Ziyao Wei我的代码中有一个bug('s2'的赋值被关闭了一个)。更新后的代码已经过测试并可以正常工作感谢您指出存在错误。 – 2013-04-26 09:15:48

1

原始long变量可以保存范围从-9,223,372,036,854,775,8089,223,372,036,854,775,807(含)的值。

计算结果显示fffff8000261e000十六进制为18,446,735,277,656,498,176十进制,这显然是超出范围。相反,fffff8000261e000十六进制为1,152,912,708,553,793,536十进制,这在界限内显然是如此。

正如大家在这里提出的,使用BigInteger来解释这种情况。例如,BigInteger bi = new BigInteger("fffff8000261e000", 16);将解决您的问题。同样,new java.math.BigInteger("fffff8000261e000", 16).toString()将完全产生18446735277656498176

+0

有趣,但它不回答这个问题。除非您提出解决方案,否则这适合作为评论。 – Gamb 2013-04-25 14:15:54