What Happened in overflow of short vs log variables in Java - java

I am new to java, and I don't understand the differences between these two:
Lets init some variables for the overflow:
byte myByte = 100;
short myShort = 5000 ;
int myInt = 2_000_150_000;
I know whenever I got variable and arithmetic I need to do a casting with (long)
long myLong = (long)(50_000 + 10 * (long)(myByte + myShort + myInt));
long myLong2 =(long)(50_000 + 10 * (myByte + myShort + myInt));
sysout(myLong);
sysout(myLong2);
OUTPUT:
20001601000
-1473235480
but why do I need to do it outside two times?
for short type, this works differently:
short myShortTest = (short)(50_000 + 10*(short)(myByte + myInt +myShort));
short myShortTest2 = (short)(50_000 + 10*(myByte + myInt +myShort));
sysout(myShortTest);
sysout(myShortTest2);
OUTPUT
13800
13800

Whenever an overflow happens, an int will move to the other end of the boundary as seen in the output of the following program:
public class Main {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MAX_VALUE + 1);
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MIN_VALUE - 1);
}
}
Output:
2147483647
-2147483648
-2147483648
2147483647
In the case of test1, because of casting to long, the result of the intermediate calculation [10*(long)(myByte + myShort + myInt)] was stored as long which can accommodate the result without an overflow and hence you got the correct value.
In the case of test2, in lack of proper cast, the result of the intermediate calculation [10*(myByte + myShort + myInt)] was stored as int but the value overflew for int and hence you got the negative value.

Your first version reads: add up my variables, treat the result as a long, multiply by 10, add 50000 and treat that as a long.
Your second version reads: add up my variables (result is an int), multiply by 10 (which is still an int but might be overflown), add 50000 (still a possibly overflown int) and treat that as a long.
So your fist version starts to treat the sum as a long value and reserves sufficient memory while your second version does this step at the very end, working with lower memory until then.

Related

Why variable of long type is giving different answer after casting and before casting in the following code as both are of type long?

byte byteChallenge = 68;
short shortChallenge = 190;
int intChallenge = 2147483647;
long longChallenge = (50000L + 10L * (byteChallenge + shortChallenge + intChallenge));
long longChallengeX = 50000L + 10L * ((long) byteChallenge + (long) shortChallenge + (long)
intChallenge);
System.out.println(longChallenge);
System.out.println(longChallengeX);
The output I'm getting is:
-21474783910
21474889050
The tricky part is int intChallenge = 2147483647 constant which is the maximum value for positive int (see Integer.MAX_VALUE).
When you perform byteChallenge + shortChallenge + intChallenge it is an int arithmetic statement which results in integer overflow. In your example the integer overflow result is a negative number.
When you perform (long) byteChallenge + (long) shortChallenge + (long) intChallenge it is long arithmetic. Since long supports much larger values than int there is no overflow.
In the first scenario, the sub-expression (byteChallenge + shortChallenge + intChallenge) is basically "byte + short + int". Java evaluates this part first, before multiplying by 10 and adding to 50000.
Since the sub-expression doesn't involve a long type, Java has no reason to make the result type of the expression long, so the first two operands is only promoted to int and the three ints are added together to give another int. This causes an overflow, making the result very negative.
In the second case, you explicitly cast all three operands to long before operating on them, so the type of the sub-expression is resolved to be long.
The lesson here is that nested expressions are treated the same as any other expressions. (byteChallenge + shortChallenge + intChallenge) doesn't get special treatment just because it is multiplied with a long. Its value is still evaluated the same way.

Multiply an int in Java by itself

Why if I multiply int num = 2,147,483,647 by the same int num is it returning 1 as result? Note that I am in the limit of the int possible value.
I already try to catch the exception but still give the result as 1.
Before any multiplication java translates ints to binary numbers. So you are actually trying to multiply 01111111111111111111111111111111 by 01111111111111111111111111111111. The result of this is something like
1111111111111111111111111111111000000000000000000000000000000001. The int can hold just 32 bits, so in fact you get 00000000000000000000000000000001 which is =1 in decimal.
In integer arithmetic, Java doesn't throw an exception when an overflow occurs. Instead, it just the 32 least significant bits of the outcome, or equivalently, it "wraps around". That is, if you calculate 2147483647 + 1, the outcome is -2147483648.
2,147,483,647 squared happens to be, in binary:
11111111111111111111111111111100000000000000000000000000000001
The least significant 32 bits of the outcome are equal to the value 1.
If you want to calculate with values which don't fit in 32 bits, you have to use either long (if 64 bits are sufficient) or java.math.BigInteger (if not).
int cannot handle just any large value.Look here. In JAVA you have an exclusive class for this problem which comes quite handy
import java.math.BigInteger;
public class BigIntegerDemo {
public static void main(String[] args) {
BigInteger b1 = new BigInteger("987654321987654321000000000"); //change it to your number
BigInteger b2 = new BigInteger("987654321987654321000000000"); //change it to your number
BigInteger product = b1.multiply(b2);
BigInteger division = b1.divide(b2);
System.out.println("product = " + product);
System.out.println("division = " + division);
}
}
Source : Using BigInteger In JAVA
The Java Language Specification exactly rules what should happen in the given case.
If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format. As a result, if overflow occurs, then the sign of the result may not be the same as the sign of the mathematical product of the two operand values.
It means, that when you multiply two ints, the result will be represented in a long value first (that type holds sufficient bits to represent the result). Then, because you assign it to an int variable, the lower bits are kept for your int.
The JLS also says:
Despite the fact that overflow, underflow, or loss of information may occur, evaluation of a multiplication operator * never throws a run-time exception.
That's why you never get an exception.
My guess: Store the result in a long, and check what happens if you downcast to int. For example:
int num = 2147483647;
long result = num * num;
if (result != (long)((int)result)) {
// overflow happened
}
To really follow the arithmetics, let's follow the calculation:
((2^n)-1) * ((2^n)-1) =
2^(2n) - 2^n - 2^n + 1 =
2^(2n) - 2^(n+1) + 1
In your case, n=31 (your number is 2^31 - 1). The result is 2^62 + 2^32 + 1. In bits it looks like this (split by the 32bit boundary):
01000000000000000000000000000001 00000000000000000000000000000001
From this number, you get the rightmost part, which equals to 1.
It seems that the issue is because the int can not handle such a large value. Based on this link from oracle regarding the primitive types, the maximum range of values allowed is 2^31 -1 (2,147,483,647) which is exactly the same value that you want to multiply.
So, in this case is recommended to use the next primitive type with greater capacity, for example you could change your "int" variables to "long" which have a bigger range between -2^63 to 2^63-1 (-9223372036854775808 to 9223372036854775807).
For example:
public static void main(String[] args) {
long num = 2147483647L;
long total = num * num;
System.out.println("total: " + total);
}
And the output is:
total: 4611686014132420609
I hope this can help you.
Regards.
According to this link, a Java 'int' signed is 2^31 - 1. Which is equal to 2,147,483,647.
So if you are already at the max for int, and if you multiply it by anything, I would expect an error.

Arithmetic Operation in Java

Assume that I have one arithmetic function which will add two long variables and return a long value. If pass Long.MaxValue() as an argument it wont give a perfect result. What will be the solution for that? The code below explains what I mean:
public class ArithmaticExample {
public static void main(String[] args) {
System.out.println(ArithmaticExample.addLong(Long.MAX_VALUE, Long.MAX_VALUE));
}
public static long addLong(long a,long b){
return a+b;
}
}
So you can see the wood from the trees, let's recast the problem using byte rather than long and consider
byte a = 0b01111111; // i.e. 127, the largest value of a `byte`.
byte b = 0b01111111;
byte c = (byte)(a + b);
where you need the explicit cast to circumvent conversion of a + b to an int.
Computing c by hand gives you 0b11111110. This is, of course, the bitwise representation of -2 in an 8 bit 2's complement type.
So the answer for the byte case is -2. And the same holds true for a long: there are just more 1 bits to contend with in your addition.
Note that although all this is perfectly well-defined in Java, the same cannot be said for C and C++.
If you need to add two long values of such magnitude then consider using BigInteger.
The result is -2. This is not what is expected as it seems to be more an overflow than anything else, but this result is "normal".
Long.MAX_VALUE = 9223372036854775807
Long.MAX_VALUE + 1 = 9223372036854775807
Long.MAX_VALUE + Long.MAX_VALUE = -2

My program is not working properly

I have the following code in Java but it overflows when it shouldn't. Why?
public classO {
public static void main(String[] args) {
int big = Integer.MAX_VALUE;
System.out.println("big = " + big);
long bigger = big + 2;
System.out.println("bigger = " + bigger);
}
}
I get this output:
big = 2147483647
bigger = -2147483647
Why does it overflow? I have defined bigger as a long. What is wrong?
big + 2 is an integer operation and leads to your overflow (first you add two integers and afterwards you cast it to a long but at the point of castig the overflow has already happend).
use the following code to create a Long operation by casting your int before the add operation:
long bigger = (long) big + 2L;
big+2 will overflow as big is max. value while (long) big not
long bigger = (long) big +2
will work for you as it will treat big as long instead of integer.So make a cast of float to it.

How to check if number fits primitive type in java?

I need do to some input validation but run into a question and I do not seem to find an answer (even with Google). The problem is simple: I have 2 positive integers on the input, and I need to check if their product fits int type in Java.
One of my attempts was to compare product with Integer.MAX_VALUE, but it seems if the product is too big for integer, value becomes negative.
I wanted to reason that product is too big by change in sign, but it seems if the product is "way too big" it will become positive again.
Could someone advise me how to detect if number becomes too big?
Many thanks in advance!
If you are doing a UI, you are presumably in no particular hurry. So you could use a BigInteger and then test the product against MAX_VALUE.
Cast the value to int and see if the value is the same. A simple check looks like
double d =
long l =
BigInteger bi =
if (d == (int) d) // can be represented as an int.
if (l == (int) l) // can be represented as an int.
int i = bi.intValue();
if (bi.equals(BigInteger.valueOf(i)))
If the value is the same when cast back, there is no loss of information and you can use an int value.
Searched and found the following:
Java is cavalier about overflow. There are no compile-time warnings or run-time exceptions to let you know when your calculations have become too big to store back in an int or long. There is no warning for float or double overflow either.
/**
* multiplies the two parameters, throwing a MyOverflowException if the result is not an int.
* #param a multiplier
* #param b multiplicand
* #result product
*/
public static int multSafe(int a, int b) throws MyOverflowException
{
long result = (long)a * (long)b;
int desiredhibits = - ((int)( result >>> 31 ) & 1);
int actualhibits = (int)( result >>> 32 );
if ( desiredhibits == actualhibits )
{
return(int)result;
}
else
{
throw new MyOverflowException( a + " * " + b + " = " + result );
}
}
You could create a BigInteger from your input value and use its intValue() method to convert. If the BigInteger is too big to fit in an int, only the low-order 32 bits are returned. So you need to compare the resulting value to your input value to ensure it was not truncated.

Categories

Resources