Reputation: 377
I've done some searching on google, but I can't seem to find what I'm looking for. I'm trying to find out some detailed information on the way arithmetic works in Java. For example, if you add two longs together is this using the same addition operator that is used when adding two ints together? Also, what is going on under the hood when you mix longs and ints in arithmetic expressions like this:
long result;
long operand a = 1;
int operand b = 999999999;
result = a + b;
If anyone could shed some light on this or post links to relevant articles that would be awesome. Thanks!
EDIT: Thanks for the replies so far. Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
Upvotes: 13
Views: 28223
Reputation: 1
The answers point out to arithmetic promotion. But with that in mind I trapped into the following pitfall (shame on me) which I want to point out here: If there are more than two operands to me it seems that calculation is performed left to right and arithmetic promotion occurs if the actual two operands in focus have a differnt type. Thus the following code produces different results for s1 and s2. My explanation to this is: When calculating s1 first a and b are added as two integers (and an overflow occurs) then to the result of that c (a long) is added. When calculating s2 first c and b are added (as long) and then a is added (promoted as long) thus no overflow occurs.
final int a = Integer.MAX_VALUE;
final int b = 1;
final long c = 1L;
final long s1 = a + b + c;
final long s2 = c + b + a;
System.out.println("s1=" + s1 + ", s2=" + s2);
The output will be:
s1=-2147483647, s2=2147483649
Upvotes: 0
Reputation: 29629
When mixing types the int is automatically widened to a long and then the two longs are added to produce the result. The Java Language Specification explains the process for operations containing different primative types.
Specifically, these are the types each primative will widen to without requiring a cast:
Upvotes: 16
Reputation: 21
This simple example could clear the doubts about data type conversion in case of arithmetic operations in java.
byte a = 1;
short b = 1;
System.out.println(a+b); //Output = 2
Object o = a+b; //Object becomes int
System.out.println(o.getClass().getName()); //Output = java.lang.Integer
int c = 1;
System.out.println(a+b+c); //Output = 3
o = a+b+c; //Object becomes int
System.out.println(o.getClass().getName()); //Output = java.lang.Integer
long d = 1l;
System.out.println(a+b+c+d); //Output = 4
o = a+b+c+d; //Object becomes long
System.out.println(o.getClass().getName()); //Output = java.lang.Long
float e = 1.0f;
System.out.println(a+b+c+d+e); //Output = 5.0
o = a+b+c+d+e; //Object becomes float
System.out.println(o.getClass().getName()); //Output = java.lang.Float
double f = 1.0;
System.out.println(a+b+c+d+e+f); //Output = 6.0
o = a+b+c+d+e+f; //Object becomes double
System.out.println(o.getClass().getName()); //Output = java.lang.Double
Following is the order of data types according to range in java:
byte<short<int<long<float<double
This is the order in which widening will happen.
Note: float has more range than long, but has smaller size.
Upvotes: 2
Reputation: 814
int a=5;
long b=10;
a+=b;
System.out.println(a);
The main difference is that with a = a + b
, there is no typecasting going on, and so the compiler gets angry at you for not typecasting.
But with a += b
, what it's really doing is typecasting b
to a
type compatible with a
.
Upvotes: 2
Reputation: 199333
See: Conversions and promotions
According to that, your int
is promoted to long
and then is evaluated.
Same happens with, for instance, int
+ double
and the rest of the primitives. ie.
System.out( 1 + 2.0 );// prints 3.0 a double
As for the addition operator I'm pretty much it is the same, but I don't have any reference of it.
A quick view to the compiler's source reveals they are different.
Namely iadd
for int addition and ladd
for long addition:
See this sample code:
$cat Addition.java
public class Addition {
public static void main( String [] args ) {
int a = Integer.parseInt(args[0]);
long b = Long.parseLong(args[0]);
// int addition
int c = a + a;
// long addition
long d = a + b;
}
}
$javac Addition.java
$
When compiled the byte code generated is this:
$javap -c Addition
Compiled from "Addition.java"
public class Addition extends java.lang.Object{
public Addition();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: aload_0
1: iconst_0
2: aaload
3: invokestatic #2; //Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
6: istore_1
7: aload_0
8: iconst_0
9: aaload
10: invokestatic #3; //Method java/lang/Long.parseLong:(Ljava/lang/String;)J
13: lstore_2
14: iload_1
15: iload_1
16: iadd
17: istore 4
19: iload_1
20: i2l
21: lload_2
22: ladd
23: lstore 5
25: return
}
Look at line 16
it says: iadd
( for int addition ) while the line 22
says ladd
( for long addition )
Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
Yes, and it's also "safe" to perform arithmetic with smaller sizes, in the sense, they don't break the program, you just lose information.
For instance, try adding Integer.MAX_VALUE to Integer.MAX_VALUE
to see what happens, or int x = ( int ) ( Long.MAX_VALUE - 1 );
Upvotes: 7
Reputation: 80192
this is called arithmetic promotion. for details look at http://www.cafeaulait.org/course/week2/22.html
Upvotes: 3
Reputation: 719616
Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
It depends what you mean by safe. It certainly won't avoid you needing to consider the possibility of overflow.
Upvotes: 3