I have a test tomorrow and I can't understand my books explanation, I appreciate the help:
public class TestClass{
public static void main(String[] args) throws Exception{
int a = Integer.MIN_VALUE;
int b = -a;
System.out.println( a+ " "+b);
}
}
Output: -2147483648 -2147483648
Why does this print 2 negative numbers of the same magnitude and not a positive and negative?
Because of silent integer overflow: Integer.MIN_VALUE is -2^31 and Integer.MAX_VALUE is 2^31-1, so -Integer.MIN_VALUE is 2^31, which is Integer.MAX_VALUE + 1, which by definition is too large for an integer. So it overflows and becomes Integer.MIN_VALUE...
You can also check that:
System.out.println(Integer.MAX_VALUE + 1);
prints the same thing.
More technically, the result is defined by the Java Language Specification #15.18.2:
If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.
Basically, because Integer.MAX_VALUE is actually only 2147483647, so -Integer.MIN_VALUE, which would be +2147483648, actually overflows the capacity of the internal binary representation of integers. Thus, the result "loops around" back to Integer.MIN_VALUE, or -2147483648.
If you did long b = -((long)a); instead, you would get the expected result.
To show this even more clearly:
Integer.MIN_VALUE is -2^31 = -2147483648
Integer.MAX_VALUE is 2^31-1 = 2147483647
/*notice this is 1 less than the negative value above*/
Integer.MAX_VALUE can not take 2147483648. This is too large number for Integer by exactly 1. This causes the number to go back on the scale from max value back to starting poing which is the min value.
A fixed number of binary bits can encode an even number of things. That means that you can't have a sequence that's exactly centered on zero, since that would require an is number of things to be symmetrical. The closest thing you can get to having zero in the middle of the sentence is to split it as either negative and non-negative, or positive and non-positive. Normal twos complement encoding does the former. So 32 bits span the range from -2^31 to 2^31-1. Zero is in the non-negative half of the sequence, and you have one negative number that can not be properly negated.
Java ints are stored in a 32-bit two's compliment form. Similar results applies for all two's compliment representations. The anomalous behavior is due to the extra negative integer which is an artifat of two's compliment.
-2147483748 has a leadbitwise representation of
10000000 00000000 00000000 00000000
and the negative of a number is achieved by flipping all the bits and adding one to it. The largest positive int will have a bitwise representation of
01111111 11111111 11111111 11111111
which is 2147483647. We then add one more, so bitwise, we have
10000000 00000000 00000000 00000000 == -2147483648
This extra integer is an artifact of the two's compliment representation and operations with this number can have undesirable consequences. -2147483748 is indeed unique among the ints!
Related
According to the documentation for java.util.Random, the Java class
implements nextFloat by next(24) / ((float)(1 << 24)) (ie. a random non-negative integer with 24 bits divided by 224). The documentation claims that all 224 possible values can be returned. They are between 0 (inclusive) and 1 (exclusive). However, I don't think that is true.
First, note that according to the IEC 559 (IEEE 754) standard, float has 23 fraction bits. But there is an implicit leading bit (to the left of the binary point) with value 1, unless the exponent is stored with all zeros. Therefore, it is true that there are a total of 224 values of type float that are between 0 (inclusive - not counting negative zero) and 1 (exclusive), but exactly half of these numbers are subnormal (all bits in the exponent are 0), which makes them all less than 2-126. Therefore, none of these numbers can be generated by the implementation. This is because they are all strictly smaller than 2-24 which is used in the implementation.
The layout of float can be found at Single-precision floating-point format.
So what is it that I am missing?
In the interval [+0, 1), there are 127•223 values representable in float, not 224. There is one for each combination of an exponent encoding field from 0 to 126, inclusive, with each value of 23 bits in the significand encoding field.
Every value in the form m•2−24, with 0 ≤ m < 224, is representable. The smallest non-zero value in this form is 2−24, which is represented with an exponent code of 103 and a significand code of 0. The mathematical exponent is the code, 103, minus the bias, 127, which equals −24, and the mathematical significand is 1.
For any such m other than zero, let b be the position number of its leading 1 bit (numbering from 0 for the low bit). Then m•2−24 is encoded in float with an exponent code of b+103 and a significand code of m•224− b−224. For m = 0, it is encoded with all zero bits.
None of the numbers in this form are subnormal.
Every number of type float has 23 fraction bits and 8 exponent bits.
We show how to use float to precisely represent every number n of the form 0.b1b2b3...b24.
Let i be the smallest number such that bi is non-zero.
If no such i exists then n=0, which can be represented in float. Otherwise,
n = 2-i2i0.b1b2b3... b24.
The part 2-i can clearly be represented by the 8 bits
of exponents in float.
Furthermore, the part
2i0.b1b2b3... b24
is of the form 1.bi+1bi+2...b24 which has at most 23 fraction bits.
Therefore, n can be precisely represented in float.
All that remains is to uniformly generate random integers of the form
b1b2b3... b24 and then divide them by 224 which is exactly what Oracle is suggesting.
I have a test tomorrow and I can't understand my books explanation, I appreciate the help:
public class TestClass{
public static void main(String[] args) throws Exception{
int a = Integer.MIN_VALUE;
int b = -a;
System.out.println( a+ " "+b);
}
}
Output: -2147483648 -2147483648
Why does this print 2 negative numbers of the same magnitude and not a positive and negative?
Because of silent integer overflow: Integer.MIN_VALUE is -2^31 and Integer.MAX_VALUE is 2^31-1, so -Integer.MIN_VALUE is 2^31, which is Integer.MAX_VALUE + 1, which by definition is too large for an integer. So it overflows and becomes Integer.MIN_VALUE...
You can also check that:
System.out.println(Integer.MAX_VALUE + 1);
prints the same thing.
More technically, the result is defined by the Java Language Specification #15.18.2:
If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.
Basically, because Integer.MAX_VALUE is actually only 2147483647, so -Integer.MIN_VALUE, which would be +2147483648, actually overflows the capacity of the internal binary representation of integers. Thus, the result "loops around" back to Integer.MIN_VALUE, or -2147483648.
If you did long b = -((long)a); instead, you would get the expected result.
To show this even more clearly:
Integer.MIN_VALUE is -2^31 = -2147483648
Integer.MAX_VALUE is 2^31-1 = 2147483647
/*notice this is 1 less than the negative value above*/
Integer.MAX_VALUE can not take 2147483648. This is too large number for Integer by exactly 1. This causes the number to go back on the scale from max value back to starting poing which is the min value.
A fixed number of binary bits can encode an even number of things. That means that you can't have a sequence that's exactly centered on zero, since that would require an is number of things to be symmetrical. The closest thing you can get to having zero in the middle of the sentence is to split it as either negative and non-negative, or positive and non-positive. Normal twos complement encoding does the former. So 32 bits span the range from -2^31 to 2^31-1. Zero is in the non-negative half of the sequence, and you have one negative number that can not be properly negated.
Java ints are stored in a 32-bit two's compliment form. Similar results applies for all two's compliment representations. The anomalous behavior is due to the extra negative integer which is an artifat of two's compliment.
-2147483748 has a leadbitwise representation of
10000000 00000000 00000000 00000000
and the negative of a number is achieved by flipping all the bits and adding one to it. The largest positive int will have a bitwise representation of
01111111 11111111 11111111 11111111
which is 2147483647. We then add one more, so bitwise, we have
10000000 00000000 00000000 00000000 == -2147483648
This extra integer is an artifact of the two's compliment representation and operations with this number can have undesirable consequences. -2147483748 is indeed unique among the ints!
I was trying to check different inputs and creating infinite loops in java and I found that once the int is getting incremented over the maximum limit it turns in to negative -2147482958. I am just increasing the int in infinite loop...
Code:
public static void infiniteLoop(){
for(int i=0;i>-1;i++){
i = i + 1000;
System.out.println(i);
}
}
The last to value gets printed out is,
2147483337
-2147482958
Now, Why does it goes to negative?
Why does it goes to negative?
Because that is what is specified to happen in Java when an int calculation overflows.
JLS 15.18.2
"If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values."
(This doesn't explicitly say that overflow always gives a negative number. And it doesn't always. But if you apply the rule, it does explain why incrementing Integer.MAX_VALUE by +1 gives you Integer.MIN_VALUE ...)
According to the documentation:
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 (0x80000000) and a maximum value of 2,147,483,647 (0x7FFFFFFF) (inclusive)
So when you add one to an integer's max value:
0x7FFFFFFF + 0x00000001 = 0x80000000 (-2,147,483,648)
Because when the value of an int reaches Integer.MAX_VALUE, incrementing it causes overflow and hence wraps around to Integer.MIN_VALUE.
To use larger integers, use a long instead which has 64 bits.
Because int ranges from -2,147,483,648 to 2,147,483,647. Hence,once it reaches it upper limit, it overflows and starts from the negative.
See the docs:
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive)
when i am looking at the wikipedia page for Offset Binary, i cant follow the following sentence:
Unusually however, instead of using "excess 2^(n-1)" it uses "excess
2^(n-1)-1" which means that inverting the leading (high-order) bit of
the exponent will not convert the exponent to correct twos' complement
notation.
can anyone explain it in details and give me some examples?
This is the range of exponents which allows you to calculate 1/Float.MAX_VALUE and 1/Float.MIN_NORMAL without going to zero or Infinity. If there was one more negative exponent and one less positive exponent, (with an offset of 128) 1/Float.MIN_NORMAL would be Infinity.
The exponent in floating point is offset rather than plain two-complement.
e.g. for double a 0 exponent is 11-bit value for 1023 or 0b0111111111, -1 is 1022 or 0b0111111110, +1 is 1024 0b10000000000.
In twos-complement, the number would be 0 is 0b00000000000, -1 is 0b11111111111, and +1 is 0b00000000001
A property of using an offset, is that the maximum is half the possible number of values. i.e. for 11 bits the range is -1023 to 1024 instead of -1024 to 1023.
Another property is that number can be compared by just comparing the integer values.
i.e.
long l1 = Double.doubleToRawLongBits(d1);
long l2 = Double.doubleToRawLongBits(d2);
if (l1 > l2) // like d1 > d2
The only difference is in the handling of NaN and -0.0 The approach Double.compare(double, double) uses is based on this.
why this code returns wrong value?
int i=Integer.MAX_VALUE+1;
long l=Integer.MAX_VALUE+1;
System.out.println(l);
System.out.println(i);
When you add 1 to Integer.MAX_VALUE it overflows and wraps around to Integer.MIN_VALUE.
This happens because Java uses two's complement to represent integers. An example in 4 bits:
0000 : 0
0001 : 1
...
0111 : 7 (max value)
1000 : -8 (min value)
...
1110 : -2
1111 : -1
So when you add 1 to 0111 (max) it goes to 1000, and that's the minimum. Expand this idea to 32-bits and it works the same way.
As for why your long is also showing an incorrect result, it's because it's performing addition on int s and then implicitly converting to long. You need to do:
long l = (long) Integer.MAX_VALUE + 1
System.out.println(l); // now prints the correct value
As the name says Integer.MAX_VALUE is the max value available for an Integer. In java when an Integer goes over its max value by 1 (or overflows by 1) then its value will be Integer.MIN_VALUE.
If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.
Beware, with Float or Double you won't have this overflow, the value will be POSITIVE_INFINITY
An operation that overflows produces a signed infinity, an operation that underflows produces a denormalized value or a signed zero, and an operation that has no mathematically definite result produces NaN.
Resources :
JLS - MIN_VALUE & MAX_VALUE
Additive Operators (+ and -) for Numeric Types
You are overflowing the 32 bit integer type here by trying to store a value that cannot be represented by this type (2^31 - 1):
int i = Integer.MAX_VALUE + 1;
Java integer is 32 bit signed type ranges from: -2,147,483,648 to 2,147,483,647.
You can't set i integer variable as you did in i=Integer.MAX_VALUE+1;