• Post Reply Bookmark Topic Watch Topic
  • New Topic

NumberFormatException  RSS feed

 
abhijitg ga
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

in our application we are using the below call to convert the long into a String in HexFormat.


the String returned by valueToString is stored in database. Later the value is read from the DB and used in the below function


however Long.valueOf throws NumberFormatException ,


Caused by: java.lang.NumberFormatException: For input string: "ffffe75f01499c00"

at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Long.parseLong(Long.java:415)
at java.lang.Long.valueOf(Long.java:491)

This is EXPECTED as ffffe75f01499c00 (in hex) is much more than the max limit of the long which is 9,223,372,036,854,775,807 (in decimal)


I am not able to figure how the first function "valueToString" would return a string "ffffe75f01499c00" ...there is no processing except for storing the value in Database and then reading it back again and converting back to long using "stringToValue" ...

Any pointers?

 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As you already noticed the value doesn't fit into a long. You can solve this by using BigInteger which theoretically doesn't have any limitations.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think the question is more "how did something start as a long, and after what is theoretically a round trip no longer fits into a long".

The obvious question to be is, what was the original value of valLong? Then, what was the original result of Long.toString(valLong,16)? It shouldn't be hard to track down where the weirdness is happening, and that might give clues to what is causing it.
 
abhijitg ga
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks Matthew for the reply.

In a test class i can debug what is going on.

however the application is deployed at the customer end and cannot be debugged using any log files.

I was looking to find out whether theoretically is there any chance that such thing can happen with Long.

i.e. Long.toString(longVal,16) return a String that is too large to fit into long while doing Long.valueOf(valString, 16);

 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've got a guess as to what's happening, but I'm still not sure why it's happening.

Those leading Fs look suspicious. Could the initial value be negative? My guess is that it's getting confused between signed and unsigned representations of the number. Read the documentation for Long.toString(val, 16) and Long.toHexString() - they feel like they ought to be the same but they treat negative numbers differently. However, my brief reading of the documentation would suggest that toString ought to give you the behaviour you want, whereas toHexString might give the problem you're seeing. But I could be wrong. I'd suggest experimenting with some negative inputs and see what happens.
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

It may be because integer literals are all unsigned. If you write them in decimal, for an byte for example, you are allowed 0..2147483648, but there are restrictions on the use of 2147483648. I see the new edition of the Java™ Language Specification is now available online But you see the limits for literals in hex or binary would be 0x0..0xffff_ffff or 0b0..0b1111_1111_1111_1111_1111_1111_1111_1111. So the range of hex/decimal literals is double that of decimal literals. So you can get a hex value in unsigned > 0x7fff_ffff from Integer.toHexString(). Now, you see that parseInt has restrictions on its arguments.
I think they have contrived a situation where the range of strings which can be used as an integer literal is different from the range of Strings accepted by parseInt.
I haven’t checked about Longs, but suspect the same occurs there.
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matthew Brown wrote:I've got a guess as to what's happening, but I'm still not sure why it's happening.

Those leading Fs look suspicious. Could the initial value be negative? My guess is that it's getting confused between signed and unsigned representations of the number. Read the documentation for Long.toString(val, 16) and Long.toHexString() - they feel like they ought to be the same but they treat negative numbers differently. However, my brief reading of the documentation would suggest that toString ought to give you the behaviour you want, whereas toHexString might give the problem you're seeing. But I could be wrong. I'd suggest experimenting with some negative inputs and see what happens.

I think you're on to something. That String contains 16 characters. Each represents 16 bits so the total is 64 bits. In other words, a full long.

The maximum value of a long is 7fffffffffffffff. ffffe75f01499c00 is "larger" than that, and is therefore negative. Basically, any 16-char String that does not start with 7 or below is negative. You can't use Long.parseLong on these Strings. You would need to do the parsing manually. A quick attempt without validation:

I found something else out when testing though. Long.toHexString(valLong) will return "ffffe75f01499c00". However, for the same long, Long.toString(valLong, 16) will return "-18a0feb66400". If you switch to that method you should have no problem parsing the Strings back into longs.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:
I found something else out when testing though. Long.toHexString(valLong) will return "ffffe75f01499c00". However, for the same long, Long.toString(valLong, 16) will return "-18a0feb66400". If you switch to that method you should have no problem parsing the Strings back into longs.


Right. The toString(val, radix) and parse(string, radix) complement each other, but do not deal in twos complement.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:
I found something else out when testing though. Long.toHexString(valLong) will return "ffffe75f01499c00". However, for the same long, Long.toString(valLong, 16) will return "-18a0feb66400". If you switch to that method you should have no problem parsing the Strings back into longs.

Oh, good! Because I didn't test it, but that's what I interpreted the documentation to say.

Which does mean the behaviour doesn't seem to be quite matching the code posted, unfortunately.
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're right about that. I checked it with both Java 6 and Java 7 and both return different values for Long.toString and Long.toHexString. I've also checked the source code of Java 1.4 and it too returns different values (toHexString calls toUnsignedString).
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!