posted 3 years ago

I'm new on here, and also new to posting on a forum.

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

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

posted 3 years ago

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

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

posted 3 years ago

- 1

here's a simplified example. Let's say an int used only 4 bytes for an int. we use one of the three bits to track the sign of the number...so a '0' in the left-most bit means non-negative (i.e. 0 or greater), and a 1 will mean negative.

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.

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

posted 3 years ago

Thank you Henry,

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

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

posted 3 years ago

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

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

Campbell Ritchie

Marshal

Posts: 56518

172

posted 3 years ago

- 1

The number formats are what people have agreed on over several decades in computing. They support things which are mathematically incorrect: for example floating‑point arithmetic supports −zero which doesn't actually exist. So you have to make do with a compromise to fit with the constraints of binary arithmetic.

posted 3 years ago

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

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

HIH

Winston

- 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

Campbell Ritchie

Marshal

Posts: 56518

172

posted 3 years ago

- 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 workthe same way, regardless of sign, . . .

posted 3 years ago

Actually, that statement is wrong, since

You could, however, see different behaviour with

Winston

Winston Gutkowski wrote:...and if you print out their hex values, you'll see that they're also identical beforeand 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

Articles by Winston can be found here

Don't get me started about those stupid light bulbs. |