I've grown up knowing it is good to ask why? And so, I seek some help here after several days of debugging.

Take a Java (Oracle SE 7 JVM) long, primitive or it's wrapper class... assign a variable with the value slightly less than 2^63-1 (the maximum value... i.e. infinity? for a long); keep adding 1. What happens?

You quite quickly get - minimum long, or minus infinity (?).

Infinity is my perspective from a Mathematics degree.

It is not behavior I expected, is there someone who can point me in the direction of an explanation? I am eager to know/learn

Stephen

- 1

Stephen Fitzsimmons wrote:

Take a Java (Oracle SE 7 JVM) long, primitive or it's wrapper class... assign a variable with the value slightly less than 2^63-1 (the maximum value... i.e. infinity? for a long); keep adding 1. What happens?

You quite quickly get - minimum long, or minus infinity (?).

Infinity is my perspective from a Mathematics degree.

It is not behavior I expected, is there someone who can point me in the direction of an explanation? I am eager to know/learn

Welcome to the ranch !!

Java longs do not support the concept of infinity. If you need to have infinity then you need to use the floating point primitives -- either float or double.

As for the behavior of long, Java supports the Twos Complement format. And when you add one to the maximum value for long, it will roll around to the minimum value for long. This is simply how it works.

And BTW, adding one to Float.POSIVITY_INFINITY will yield an answer of Float.POSITIVE_INFINITY.

Henry

- 1

So, lets start with zero, and start adding 1 to it..

0000 == 0

0001 == 1

0010 == 2

0011 == 3

0100 == 4

0101 == 5

0110 == 6

0111 == 7

so far, so good. now let's add one more:

1000

hmmm....now we have a problem. the leading '1' tells me the number is negative. Now I need to use "Two's Complement" to figure out what the value really is (you can google that to find out what exactly it is). Basically, you invert all the bits and add 1. So 1000 becomes 0111. Add 1, and you get 1000. that converts to 8. I know from before i need a negative number, so 1000 == -8 (again - I am assuming an int is only 4 bytes).

So the same thing happens with an int. once you get to 0111 1111 1111 1111 1111 1111 1111 1111 and add 1 to it, you 'roll over' from positive numbers into negative numbers, due to the binary addition.

There are only two hard things in computer science: cache invalidation, naming things, and off-by-one errors

I was using the long primitive to get a big number, for my help in understanding the Fork-Join Framework (what is the biggest prime number less than 2^63-1 was my task; how about I split it into smaller pieces of work...).

I spent a day debugging and ignored the code with long.

I still don't understand why long will wrap over, and it feels a little bit 'dodgy/tricky'.

Something I will watch out for in the future, thanks.

Stephen

- 1

Stephen Fitzsimmons wrote:

I still don't understand why long will wrap over, and it feels a little bit 'dodgy/tricky'.

I'm afraid that is how it works. And this has nothing to do with Java. It pretty much works the same way on the majority of languages running on the majority of platforms. Whole number variables have to do something for overflow and underflow, and they all tend to simply wrap around.

If you don't want that, then I suggest you use something bigger than a long -- something like the BigInteger class.

Henry

- 1

- 1

Stephen Fitzsimmons wrote:I had wrongly interrupted -2^63 as being minus infinity (in Java primitive long terms) and 2^63-1 as being positive infinity (in Java primitive long terms). The outer limits of Java primitive long

It's possibly also worth mentioning that all primitive integers in Java (except

`char`) are

*signed*. The nice thing about 2s-compliment from an internal standpoint is that all addition/subtraction/increment operations work

*the same way*, regardless of sign, so adding 1 to 346 works

*exactly*the same way as adding 1 to -23 - ie, the sign only becomes significant when we want to extract (or display) the resulting value.

If you try something like:you'll notice that the "overflow"

*looks*different. However, what's happening internally is identical (the two primitives are exactly the same size, and if you print out their hex values, you'll see that they're also identical before

*and after*the '++' operation').

HIH

Winston

"Leadership is nature's way of removing morons from the productive flow" - Dogbert

Articles by Winston can be found here

- 1

…and subtracting is the same as adding with the insertion of a carry bit and an XOR gate on every input. So you can do addition and subtraction on the same circuit for the cost of one extra input.Winston Gutkowski wrote: . . . all addition/subtraction/increment operations work

the same way, regardless of sign, . . .

Winston Gutkowski wrote:...and if you print out their hex values, you'll see that they're also identical before

and afterthe '++' operation').

Actually, that statement is wrong, since

`char`'s "

`MAX_VALUE`" is 16 '1' bits and

`Short.MAX_VALUE`is a 0 followed by 15 '1' bits.

You could, however, see different behaviour with

*the same values*by setting '

`c`' to

`Short.MAX_VALUE`initially.

Winston

"Leadership is nature's way of removing morons from the productive flow" - Dogbert

Articles by Winston can be found here

Consider Paul's rocket mass heater. |