Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Negation value of Integer.MIN_VALUE

 
Jude Niroshan
Ranch Hand
Posts: 132
5
Eclipse IDE Java Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I got a question on enthuware mock exam as below; What would be the result of the code?


It prints `-2147483648 -2147483648`. When considering up-to binary digits, I could understand that output is possibly correct. But when I answering the question I thought this would definitely put a overflow situation.(because Integer.MIN_VALUE = -2147483648 and Integer.MAX_VALUE = 2147483647)

So I tried the below code myself.



How does that byte occasion detect the compile time error but in Integer case doesn't? Please help; I got confused over this now.
 
Scott Bee
Greenhorn
Posts: 16
2
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This sounds like something from Bloch and Gafter's Java Puzzlers: Traps, Pitfalls and Corner Cases (http://www.javapuzzlers.com/). It's an excellent walk-through of some of fairly obscure but interesting features of the language.

In this case, the Java compiler is promoting the variable of type byte to type int to apply the negation in line 2 of your listing. In other words...
-a
...is equivalent to...
-1 * ((int) a)

The resulting int is then assigned to a variable of type byte, causing a compiler error, and rightfully so. The byte data type can't handle the much larger int data type.

I believe if you try recompiling with line 2 reading as follows...

...it should give you a result.

If data type promotion is a new concept, check out the formal documentation here...
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

This explanation is a little more user-friendly and speaks to your example...
http://stackoverflow.com/questions/8116787/type-casting-and-automatic-type-promotion-in-java


Let us know what happens, thanks!
 
Jude Niroshan
Ranch Hand
Posts: 132
5
Eclipse IDE Java Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your reply & Welcome to Ranch.
You were indeed correct on why I should do explicit casting on Byte when it exceeds the Byte.MAX_VALUE.

All Byte, Short, Char will implicitly be cast to int when any arithmetic operations we perform on those (E.g. : Short s = Short.MAX_VALUE + 1;//Right hand side has automatically converted to int type. Therefore we need to cast the result back to short ). But for post prefix or pre prefix you DON'T need casting.

I found quite old posts which are same about my question here and here. Worth to read those posts.

Whenever we got a MIN_VALUE or MAX_VALUE related question on exam it's better to see it as in terms of binary representation.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jude Niroshan wrote:How does that byte occasion detect the compile time error but in Integer case doesn't? Please help; I got confused over this now.

The reason for this behavior is twofold.

First of all, when executing calculations Java uses a "standard" datatype. When you are calculating with integers, the result of the calculation will be an int. If you are doing some calculation with floating-points (decimals), the result will be a double. So you are applying the unary minus operator to the variable sd to negate its value. So the result of -sd will be an int and (as you know) an int can not be assigned to a byte without using an explicit cast. So this code fails to compileBut if you use compile-time constants, the compiler knows the values of the variables (hence their name "compile-time constants") and asks himself 1 question; does the value of the constant expression fit into the type of the variable? If it does, a narrowing primitive cast is used implicitly. If it doesn't, a compiler error is still given. That's the reason why this code compiles successfully
And this leads to the 2nd problem with your code snippet. Even if variable sd is marked final, the code snippet will not compileAnd the reason is very simple: the minimum value of byte is -128; if you negate this value, you'll get 128 which is outside the range of a byte and that's why you still get a compiler error.

If you want to read more about compile-time constants, you should definitely read this topic and this one.

Hope it helps!
Kind regards,
Roel
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jude Niroshan wrote:It prints `-2147483648 -2147483648`. When considering up-to binary digits, I could understand that output is possibly correct. But when I answering the question I thought this would definitely put a overflow situation.(because Integer.MIN_VALUE = -2147483648 and Integer.MAX_VALUE = 2147483647)

The output shows that the value of -sd was overflowed and therefore exactly prints Integer.MIN_VALUE. Just for completeness: the same would happen with the minimum values for integer primitive data types. Let's use byte as an exampleOutput: b[-128] resb[-128] resi[128]. So when you assign the value of the expression to an int you get the expected result (128). When assigned to a byte (using an explicit cast as the result is outside a byte's range), the result has an overflow and therefore the actual result is exactly the same as Byte.MIN_VALUE. This overflow is even more obvious when you execute this codeOutput: b[-128] resb[-49] resi[207]

Hope it helps!
Kind regards,
Roel
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jude Niroshan wrote:All Byte, Short, Char will implicitly be cast to int when any arithmetic operations we perform on those (E.g. : Short s = Short.MAX_VALUE + 1;//Right hand side has automatically converted to int type.

I have to nitpick a little bit about this statement, but it's for your own good Remember Java is case-sensitive, so there's a huge difference between byte (lower case b) and Byte (upper case b). And of course the same applies to short and Short. And Char is somewhat a special case (just like int): it's either char or Character, but Char does not exist in Java!
 
Jude Niroshan
Ranch Hand
Posts: 132
5
Eclipse IDE Java Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Roel,
As always I'm much pleased to get a response from you.
Could you please explain me this case.

-b value is equal to 128
(byte)-b value is equal to -128


Regards,
Jude
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jude Niroshan wrote:Could you please explain me this case.

-b value is equal to 128
(byte)-b value is equal to -128

First let's start with the good news: this funny (weird) looking trickery is not on the OCA (nor OCP) exam Secondly you need a basic understanding of Two's complement which is used in general computing (so not only in Java) to represent signed binary numbers. In short: the most significant (leftmost) bit determines if the value is positive (0) or negative (1).

Let's assume we have an 8-bit unsigned number. It can represent the values 0 (0000 0000) to 255 (1111 1111). However a signed 8-bit number (using two's complement) can only represent positive integers from 0 to 127 (0111 1111), because the rest of the bit combinations with the most significant bit as '1' represent the negative integers −1 to −128. Remember when using two's complement the leftmost (most significant) bit determines if the value is positive or negative.

Let's go back to our exampleThe bit representation of 128 is 1000 0000. As you (should) know an int is 32-bit data type, so to represent a value like 128 it uses 32 bits: 0000 0000 0000 0000 0000 0000 1000 0000. As you can see the most significant bit is 0 and thus the value is positive. Using two's complement, a non-negative number is represented by its ordinary binary representation. So for 0000 0000 0000 0000 0000 0000 1000 0000, that's 1*2^7 = 1*128 = 128. Phew! Exactly what we expected

Now let's focus on the second line of our exampleA byte is a 8-bit data type, so it uses only 8 bits to represent a value. So if you cast an int to a byte, only the 8 rightmost bits will be kept and all others are discarded. So after casting 0000 0000 0000 0000 0000 0000 1000 0000 to byte only the bits 1000 0000 are kept and this value is assigned to variable by. And now the leftmost (most significant) bit is 1, so the positive value (when represented as an int) suddenly has become a negative value (when represented as a byte)! In order to know the actual value, you'll need to invert (or flip) all bits (using bitwise NOT) and add 1 to the resulting value. So flipping all bits of 1000 0000 results in 0111 1111. And that's the equivalent of 127. Finally adding 1 to this result gives 128. So the value 1000 0000 using two's complement notation is equal to -128.

Hope it helps!
Kind regards,
Roel
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic