Explanation about a result - java

Hi i hav a little problem about some code that i can't give an explanation about the result i have.
//what happens?
public static void what() {
int number = 2147483647;
System.out.println(number + 33);
}
//Here is my solution for the probleme
public static void what() {
long number = 2147483647;
System.out.println(number + 33);
}
The first code with the int number as variable gives me -2147483616 as result. So when i change the int to long i get the good result expected. So question is who can help me give and explanation of why int number + 33 = -2147483616

Java integers are based on 32 Bits. The first bit is kept for the sign (+ = 0 / - = 1).
So 2147483647 equals 01111111 11111111 11111111 11111111.
Adding more will force the value to turn to negative because the first bit is turned into a 1.
10000000 00000000 00000000 00000000 equals -2147483648.
The remaining 32 you are adding to -2147483648 brings you to your result of -2147483616.

The primitive int type has a maximum value of 2147483647, which is what you are setting number to. When anything is added to this value the int type cannot represent it correctly and 'wraps' around, becoming a negative number.
The maximum value of the long type is 9223372036854775807 so the second code snippet works fine because long can hold that value with no problem.

You have reached the maximum of the primitive type int (2147483647).
If int overflows, it goes back to the minimum value (-2147483648) and continues from there.

Consider the calculation of the second snippet, and what the result actually means.
long number = 2147483647;
number += 33;
The result in decimal is 2147483680, in hexadecimal (which more easily shows what the value means) it is 0x80000020.
For the first snippet, the result in hexacimal is also 0x80000020, because the result of arithmetic with the int type is the low 32 bits of the "full" result. What's different is the interpretation: as an int, 0x80000020 has the top bit set, and the top bit has a "weight" of -231, so this result is interpreted as -231 + 32 (a negative number). As a long, the 32nd bit is just a normal bit with a weight of 231 and the result is interpreted as 231 + 32.

The primitive type int is a 32-bit integer that can only store from -2^31 to 2^31 - 1 whereas long is a 64-bit integer so it can obviously store a much larger value.
When we calculate the capacity of int, it goes from -2147483648 to 2147483647.
Now you are wondering.. why is it that when the number exceeds the limit and I add 33 to it, it will become -2147483616?
This is because the data sort of "reset" after exceeding its limit.
Thus, 2147483647 + 1 will lead to -2147483648. From here, you can see that -2147483648 + 32 will lead to the value in your example which is -2147483616.
Some extra info below:
Unless you really need to use a number that is greater than the capacity of int, always use int as it takes up less memory space.
Also, should your number be bigger than long, consider using BigInteger.
Hope this helps!

Related

Number of bits allocated to 0 is 0 in java- Why?

While learning BigInteger.valueOf(0L).bitLength() and BigInteger.valueOf(0L).bitCount() I found it is returning 0
However, the if consider 0 as a number then it should also needs one bit.
From my understanding I expect 1 as return value for both methods instead of 0.
public class Test {
public static void main(String[] args) {
int bitLength = BigInteger.valueOf(0L).bitLength();
int bitCount = BigInteger.valueOf(0L).bitCount();
System.out.println("bitLength=" + bitLength);
System.out.println("bitCount=" + bitCount);
}
}
Please help me understand why It is behaving like this ?
int bitCount()
Returns the number of bits in the two's complement representation of this BigInteger that differ from its sign bit.
For your BigInteger.valueOf(0L) example, the sign bit is 0, and there are no 1 bits, hence 0 is returned (since there are no bits that differ from the sign bit).
int bitLength()
Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
For your BigInteger.valueOf(0L) example, the minimal two's-complement representation of this BigInteger would include just the sign bit 0, so if you exclude the sign bit from the count, as the Javadoc states, you get 0.
It is interesting to note that for the same reasons BigInteger.valueOf(-1L) would also return 0 for both of these methods. Here the sign bit is 1, and after excluding it there are no other bits.
The high-level explanation is that if you have a storage system with a variable number of data bits plus a count, then the count provides some information on the value of the number, so the number of data bits required is less than a system without a count (or with a fixed count).
For normal integer types the "count" is provided by the type information and it is a fixed value. So there is an assumption, for example, that a short is 16 bits, an int is 32 bits, etc. Because of the few possibiities that a size can be (it is not fully variable) the number of bits used even for a zero value is also fixed at that number.
For BigInteger, the bit count is variable and there are various counts you can look at in the source code; some seem redundant, but the unavoidable one is the length of the data array:
final int[] mag;
Setting this array to length zero can represent a zero value, but since you still have the array count, it isn't really using zero bytes.
The bitCount and bitLength values have somewhat arbitrary definitions that don't really relate to the memory utilisation of the class but do have some functional use.
An explanation of the difference between these two methods is given in another question: What is the difference between `bitCount()` and `bitLength()` of a `BigInteger`.
Good reference about difference in both calls - Found here
Official documentation
0 is neither positive nor negative.
BigInteger h = BigInteger.valueOf(0);
System.out.println("h="+ h
+ "[binary=" + h.toString(2) + "]"
+ "[bit count="+ h.bitCount()+ "]"
+ "[bit length=" + h.bitLength() + "]");
h = h.negate();
System.out.println("h="+ h
+ "[binary=" + h.toString(2) + "]"
+ "[bit count="+ h.bitCount()+ "]"
+ "[bit length=" + h.bitLength() + "]");
//Output
//h=0[binary=0][bit count=0][bit length=0]
//h=0[binary=0][bit count=0][bit length=0]
Few samples for positive and negative numbers -
1[binary=1][bit count=1][bit length=1]
-1[binary=-1][bit count=0][bit length=0]
2[binary=10][bit count=1][bit length=2]
-2[binary=-10][bit count=1][bit length=1]
3[binary=11][bit count=2][bit length=2]
-3[binary=-11][bit count=1][bit length=2]
8[binary=1000][bit count=1][bit length=4]
-8[binary=-1000][bit count=3][bit length=3]
10[binary=1010][bit count=2][bit length=4]
-10[binary=-1010][bit count=2][bit length=4]
13[binary=1101][bit count=3][bit length=4]
-13[binary=-1101][bit count=2][bit length=4]
50[binary=110010][bit count=3][bit length=6]
-50[binary=-110010][bit count=3][bit length=6]

Issue with saturation after calculations in Java

I'm creating a Reverse Polish Calculator and am having issues with saturation. I've implemented a stack, and have found the largest number I can get to without having the issue is 2147483647. So if I push this number to the stack, then add 1, the result I get is -2147483648 (negative). What I need to do is instead of returning this negative number, return the original number 2147483647. Basically have this as a limit. The same applies to the negative side of things, where the limit is -2147483648. Let me know if I have missed any info or you need to see code.
The largest int value is 2147483647 and the smallest is -2147483648. int values wrap around, so when you add 1 to 2147483647 you get -2147483648 and when you subtract 1 from -2147483648 you get 2147483647.
If you don't want this behaviour you can do
int a = 2147483647;
a += 1.0; // a is still 2147483647
or
int a = 2147483647;
int b = (int) (a + 1.0); // b is also 2147483647
These work because a + 1.0 is calculated using double (no overflow) and the result is converted back to an int using the rule that numbers bigger than Integer.MAX_VALUE just become Integer.MAX_VALUE.

BigInteger.intValue()>1 giving incorrect boolean

I am trying to convert a BigInteger number into binary. I use a while loop to reduce the BigInteger until it is equal to 1, taking the remainder as the loop runs.
The conditional for the loop is: (decimalNum.intValue()>1).
But the program only goes through the loop once and then thinks that the BigInteger is less/equal to 1 while in reality it is around 55193474935748.
Why is this happening?
("inBinary" is an ArrayList to hold the remainders from the loop.)
Here is the while loop:
while (decimalNum.intValue()>1){
inBinary.add(0, decimalNum.mod(new BigInteger("2")).intValue()); //Get remainder (0 or 1)
decimalNum = decimalNum.divide(new BigInteger("2")); //Reduce decimalNum
}
55,193,474,935,748 doesn't fit into an int: the largest int value is 231 - 1, i.e. 2,147,483,647, which is much smaller. So you get an integer overflow.
This is explained in the javadoc, BTW:
Converts this BigInteger to an int. This conversion is analogous to a narrowing primitive conversion from long to int as defined in section 5.1.3 of The Java™ Language Specification: if this BigInteger is too big to fit in an int, only the low-order 32 bits are returned. Note that this conversion can lose information about the overall magnitude of the BigInteger value as well as return a result with the opposite sign.
If you want to compare a BigInteger to 1, then use
decimalNum.compareTo(BigInteger.ONE) > 0
To get the binary string value of your BigInteger, you could just do
bigInteger.toString(2);
EDIT : As mentionned in the comments by #VinceEmigh, converting BigInteger to int might lead to overflow.

Bitwise op unexpectedly goes negative

Can someone please explain to me why I'm getting these results?
public static int ipv4ToInt(String address) {
int result = 0;
// iterate over each octet
for(String part : address.split(Pattern.quote("."))) {
// shift the previously parsed bits over by 1 byte
result = result << 8;
System.out.printf("shift = %d\n", result);
// set the low order bits to the current octet
result |= Integer.parseInt(part);
System.out.printf("result = %d\n", result);
}
return result;
}
For ipv4ToInt("10.35.41.134"), I get:
shift = 0
result = 10
shift = 2560
result = 2595
shift = 664320
result = 664361
shift = 170076416
result = 170076550
10.35.41.134 = 170076550
This is the same result that I get when I do the math myself.
For ipv4ToInt("192.168.0.1"), I get:
shift = 0
result = 192
shift = 49152
result = 49320
shift = 12625920
result = 12625920
shift = -1062731776
result = -1062731775
192.168.0.1 = -1062731775
For this one, when I do the math manually, I get 3232235521.
Interestingly:
3232235521 = 11000000101010000000000000000001
And when I enter 1062731775 into my Windows calc and hit the +/- button, I get:
-1062731775 = 11111111111111111111111111111111 11000000101010000000000000000001
The function still works for my purposes, but I'm just really curious to know why on earth result is going negative when I do that last bit shift?
Because of bit overflow in your case!
In Java, the integer is also 32 bits and range is from -2,147,483,648 to 2,147,483,647.
12625920 << 8 crosses the limit of 2^31-1 and hence,the result turns negative...
The result just overturns from -ve side and hence,whatever range is left from the positive side is accompanied by that much from negative side!!!
As suggested by everyone,you should use long variable to avoid overflow!
All primitives in java are signed - They can be positive or negative. The highest bit is used to control this, so when it gets set, the number becomes negative.
Try using a long instead - that will give you the wanted result, as longs can be much larger without overflow being hit.
11000000101010000000000000000001 is 32 bits. The value it represents depends on how you interpret those bits:
as a 32bit signed integer, it is negative (because the left-most bit is 1)
as a 32bit unsigned integer, it is positive (like every other unsigned integer)
as the lowers bits of a long (signed or unsigned), it would give a positive value (if the left-most bits stay 0)
Java uses signed integers, so if you print the value, you'll see a negative number. That does not mean your bits are wrong.
It matters only for printing, you can use these ways for printing a positive integer:
1) change result to long (java will do the work for you).
2) handle signed int as unsigned int by yourself (possibly make a method int2string(int n) or toString(int n).
3) Integer.toUnsignedString(int) is you are using java 8.
As far as I understand, your are parsing an IP address, remember, java use signed data types, you can't have a 32 bits integer.
change result to long to fix that.

How Java processes for overflow integers [duplicate]

This question already has answers here:
Why do these two multiplication operations give different results?
(2 answers)
Closed 9 years ago.
Now signed_int max value is 2,147,483,647 i.e. 2^31 and 1 bit is sign bit, so
when I run long a = 2,147,483,647 + 1;
It gives a = -2,147,483,648 as answer.. This hold good.
But, 24*60*60*1000*1000 = 86400000000 (actually)...
In java, 24*60*60*1000*1000 it equals to 500654080..
I understand that it is because of overflow in integer, but what processing made this value come, What logic was used to get that number by Java. I also refered here.
Multiplication is executed from left to right like this
int x = 24 * 60;
x = x * 60;
x = x * 1000;
x = x * 1000;
first 3 operations produce 86400000 which still fits into Integer.MAX_VALUE. But the last operation produces 86400000000 which is 0x141dd76000 in hex. Bytes above 4 are truncated and we get 0x1dd76000. If we print it
System.out.println(0x1dd76000);
the result will be
500654080
This is quite subtle: when writing long a = 2147483647 + 1, the right hand side is computed first using ints since you have supplied int literals. But that will clock round to a negative (due to overflow) before being converted to a long. So the promotion from int to long is too late for you.
To circumvent this behaviour, you need to promote at least one of the arguments to a long literal by suffixing an L.
This applies to all arithmetic operations using literals (i.e. also your multiplication): you need to promote one of them to a long type.
The fact that your multiplication answer is 500654080 can be seen by looking at
long n = 24L*60*60*1000*1000;
long m = n % 4294967296L; /* % is extracting the int part so m is 500654080
n.b. 4294967296L is 2^32 (using OP notation, not XOR). */
What's happening here is that you are going 'round and round the clock' with the int type. Yes, you are losing the carry bits but that doesn't matter with multiplication.
As the range of int is -2,147,483,648 to 2,147,483,647.
So, when you keep on adding numbers and its exceed the maximum limit it start gain from the left most number i.e. -2,147,483,648, as it works as a cycle. That you had already mentioned in your question.
Similarly when you are computing 24*60*60*1000*1000 which should result 86400000000 as per Maths.
But actually what happens is somehow as follows:
86400000000 can be written as 2147483647+2147483647+2147483647+2147483647+..36 times+500654080
So, after adding 2147483647 for 40 times results 0 and then 500654080 is left which ultimately results in 500654080.
I hope its clear to you.
Add L in your multiplicatoin. If you add L than it multiply you in Long range otherwise in Integer range which overflow. Try to multiply like this.
24L*60*60*1000*1000
This give you a right answer.
An Integer is 32 bit long. Lets take for example a number that is 4 bit long for the sake of simplicity.
It's max positive value would be:
0111 = 7 (first bit is for sign; 0 means positive, 1 means negative)
0000 = 0
It's min negative value would be:
1111 = -8 (first bit is for sign)
1000 = -1
Now, if we call this type fbit, fbit_max is equal to 7.
fbit_max + 1 = -8
because bitwise 0111 + 1 = 1111
Therefore, the span of fbit_min to fbit_max is 16. From -8 to 7.
If you would multiply something like 7*10 and store it in fbit, the result would be:
fbit number = 7 * 10 (actually 70)
fbit number = 7 (to get to from zero to max) + 16 (min to max) + 16 (min to max) + 16 (min to max) + 15 (the rest)
fbit number = 6
24*60*60*1000*1000 = 86400000000
Using MOD as follows: 86400000000 % 2147483648 = 500654080

Categories