Long.parseLong() doesn't parse huge long values!!! JDK Bug??

H

Hans

Hello,

I have found a very strange bug in JDK 1.4. A huge long constant assignment
works fine, but if I want to parse the same huge long as string, it gives an
exception. See below!

If I remove 1 String digit, it works fine. It seems that parseLong has wrong
max value checking?

Why doesn't this work and how can I parse legal huge long values?

public static void main(String[] args)
{
// the compiler doesn't complain about this
long x = 0xFF7FFFFF80000000L;
// but this result in a NumberFormatException
long y = Long.parseLong("FF7FFFFF80000000");
}

Thanks!

Jos
 
G

Gordon Beaton

Why doesn't this work and how can I parse legal huge long values?

public static void main(String[] args)
{
// the compiler doesn't complain about this
long x = 0xFF7FFFFF80000000L;
// but this result in a NumberFormatException
long y = Long.parseLong("FF7FFFFF80000000");
}

Thanks!

The number is *larger* than the maximum positive long (x does not
contain the value you think it does, it's negative).

Have a look at java.math.BigInteger instead.

/gordon
 
C

Chris Smith

Hans said:
Why doesn't this work and how can I parse legal huge long values?

public static void main(String[] args)
{
// the compiler doesn't complain about this
long x = 0xFF7FFFFF80000000L;
// but this result in a NumberFormatException
long y = Long.parseLong("FF7FFFFF80000000");
}

I assume you meant to specify a radix of 16 to parseLong. The reason
for the NumberFormatException is that 0xFF7FFFFF80000000 is actually not
a valid value for a long. It causes a numeric overflow, and results in
a negative number. I just checked the JLS, but didn't off-hand see a
section regarding compile-time errors for use of integer literals out of
range. I can't say whether the successful parsing of the 'x' line is an
error, but I suspect it should be.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
P

pete kirkham

Hans said:
Why doesn't this work and how can I parse legal huge long values?

It's expecting a hex less than max long with a sign indicator, eg:
long x = 0xFF7FFFFF80000000L;

String str = Long.toHexString(-x);

long y = -Long.parseLong("-"+str, 16);

To bypass this wierdness, parse in 8 char chunks:
y = (Long.parseLong("FF7FFFFF", 16)<<32)|
Long.parseLong("80000000", 16);

Pete
 
S

S. Balk

Why doesn't this work and how can I parse legal huge long values?
public static void main(String[] args)
{
// the compiler doesn't complain about this
long x = 0xFF7FFFFF80000000L;
// but this result in a NumberFormatException
long y = Long.parseLong("FF7FFFFF80000000");
}

Thanks!

The number is *larger* than the maximum positive long (x does not
contain the value you think it does, it's negative).

Check out Long.MAX_VALUE for the actual maximum value.
Have a look at java.math.BigInteger instead.

I think he just needs to know how long works.
 
P

pete kirkham

Chris said:
I assume you meant to specify a radix of 16 to parseLong. The reason
for the NumberFormatException is that 0xFF7FFFFF80000000 is actually not
a valid value for a long.

What about -7 a valid value for a long?

long x = -7;

String str = Long.toHexString(x);

long y = Long.parseLong(str, 16); // throws exception
Unfortunately these functions are not inverse

str = Long.toString(x, 16);

y = Long.parseLong(str, 16); // OK

/But/ str is "-7" which is not the normal hex representation of the 64
bit signed integer -7.

The hex sequence 0xFF7FFFFF80000000L is a valid long
(-36028799166447616). If it were not, the compiler should complain.

The long literal section in the java lang spec makes no requirement that
hexadecimal is limited to positive or zero longs, and includes the
statement:

'The literals 0x8000000000000000L and 01000000000000000000000L are the
most negative long hexadecimal and octal literals, respectively. Each
has the decimal value -9223372036854775808L'
- JLS 3.10.1

The toString, parseLong and decode functions provided for any radix
reflect the convention of preprending a negative sign as used in normal
decimal representations, so do not correspond to the literal notation
for negative hex numbers.


Pete
 
C

Chris Smith

pete said:
Chris said:
I assume you meant to specify a radix of 16 to parseLong. The reason
for the NumberFormatException is that 0xFF7FFFFF80000000 is actually not
a valid value for a long.

[snip]

The hex sequence 0xFF7FFFFF80000000L is a valid long
(-36028799166447616). If it were not, the compiler should complain.

Sorry for using the "0x" prefix when discussing the actual value. Old
habit from somewhere when I'm talking in hex, and it probably was very
confusing in this context. I meant to say that the hex number
FF7FFFFF80000000 is not a valid value for a long. Yes, apparently the
sequence of characters 0xFF7FFFFF80000000L is a valid long literal... I
consider that confusing and misleading and a mistake in the language
design, but it's true nevertheless.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
X

xarax

Hans said:
Hello,

I have found a very strange bug in JDK 1.4. A huge long constant assignment
works fine, but if I want to parse the same huge long as string, it gives an
exception. See below!

If I remove 1 String digit, it works fine. It seems that parseLong has wrong
max value checking?

Why doesn't this work and how can I parse legal huge long values?

public static void main(String[] args)
{
// the compiler doesn't complain about this
long x = 0xFF7FFFFF80000000L;
// but this result in a NumberFormatException
long y = Long.parseLong("FF7FFFFF80000000");
}

Thanks!

Jos

Yes, I noticed that parseLong(str,16) doesn't like hex
representations that exceed the positive maximum value.

I believe, but haven't tested, that you may be able
to persuade parseLong(str,16) to work on such strings
by prepending a '-' to the string. However, detecting
the situation that requires the minus sign is just
as much work as parsing the string anyway.

I kludged a quick work-around by padding the string
out to 16 characters with zeroes on the left, then
splitting the string into two 8-character pieces.
I parsed each piece, shifted the left piece 32 bits,
then merged the results with bit-wise logical OR.
 
?

=?ISO-8859-1?Q?Thomas_Gagn=E9?=

Why were you using longs in the first place?

For you Java programmers, is there a numeric class that will
automatically return an integer large enough to represent whatever hex
strings you send it?
 
C

Chris Smith

Thomas said:
For you Java programmers, is there a numeric class that will
automatically return an integer large enough to represent whatever hex
strings you send it?

BigInteger.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tim Tyler

: pete kirkham wrote:
:> Chris Smith wrote:

:> > I assume you meant to specify a radix of 16 to parseLong. The reason
:> > for the NumberFormatException is that 0xFF7FFFFF80000000 is actually not
:> > a valid value for a long.
:>
:> The hex sequence 0xFF7FFFFF80000000L is a valid long
:> (-36028799166447616). If it were not, the compiler should complain.

: Sorry for using the "0x" prefix when discussing the actual value. Old
: habit from somewhere when I'm talking in hex, and it probably was very
: confusing in this context. I meant to say that the hex number
: FF7FFFFF80000000 is not a valid value for a long. Yes, apparently the
: sequence of characters 0xFF7FFFFF80000000L is a valid long literal... I
: consider that confusing and misleading and a mistake in the language
: design, but it's true nevertheless.

I think it's the implementation of Long.parseLong() which is dodgy.

Oh well - you can always write a parseLongProperly() method which
works with these top-bit-set longs.
 
C

Chris Smith

Tim said:
I think it's the implementation of Long.parseLong() which is dodgy.

Oh well - you can always write a parseLongProperly() method which
works with these top-bit-set longs.

I'm curious then: would you want to be able to trest large positive
values as negative in ALL bases? That is, would you want to be able to
parse decimal 9223372036854775808 and get back -1? Or would you like
parseLong to treat certain bases differently?

If you're not advocating treating bases differently, then I can
understand either choice.. though I would always advocate being error-
happy about overflow conditions, Java already ignores overflow in
arithmetic, and may as well ignore it in parsing text formats of numbers
as well. It was Pete's implication that hex and/or decimal should be
somehow different that took me by surprise.

The same is the reason I said that I think the literal format is
confusing. If I could say 9223372036854775808L and get a valid long (of
value -1), then it would at least be consistent and no worse than
ignoring arithmetic overflow... but that's not the case. For some
reason, 9223372036854775808L is an error, but 0x8000000000000000L is a
perfectly valid literal that's equivalent to -0x1.

Even more oddly, only one round of overflow is allowed, so
0x10000000000000000L causes an error because it overflows twice, when by
all expectations would lead you to believe it would yield 0. Granted,
the double overflow is less useful, since allowing single overflow
literals could help you pretend that you're working with unsigned
variables (as long as you refrain from certain operators). Still, it's
a very odd little special case.

In any case, it's the inconsistency between bases, and desire for
inconsistency between bases, that really feels distasteful to me.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top