Tuesday, 17 January 2012

Expression evaluation can be compile time or runtime

Consider the expression:
String a = "a" + "b" + "c";
String b = System.getProperty("blah") + "b";

The first is evaluated at compile-time. The second is evaluated at run-time. So in case of strings,
never replace constant concatenations (of any type) with StringBuilder, StringBuffer or the like. Only use those where variables are invovled and generally only when you're appending a lot of operands or you're appending in a loop.

Assignment vs compound assignment operator

Assignment operator ( = ) and compound assignment operators (like +=, -=, etc) do the same thing in the end, ie. assignment. But there is slight difference between assignment and compound operator.

Case 1 : Operands are primitive types
In this case that it silently casts the operand on the right side to the operand on the left side. So consider the following statement:
short x = 0;
int i = 123456;

So this expression will work:
x+=i //works

This will not:
x = x + i ; //compile time error -  "possible loss of precision"

To avoid unpleasant surprises, do not use compound assignment operators on variables of type byte, short, or char.

Case 2 : Case of objects
Consider following code:
Object x = "Raj ";
String i = "has taj";

Again here the case is opposite:
x = x + i ; //works

This will not work, because += will work for string, if rhs argument is string.

x+=i //error - incompatible types...


Conditional Operator with different operand types

Lets have a look at this program:
char x = ’X’;
int i = 0;
System.out.print(true ? x : 0);
System.out.print(false ? i : x);

Expected output is XX, but output printed is X88....can you guess why??????

The reason for this is mixing 2 different types of operands...here char and int.

So lets first see, how conditional operator works in java, see JLS 15.25
The rules for determining the result type of a conditional expression are too long and complex to reproduce in their entirety, but here are three key points.
1. If the second and third operands have the same type, that is the type of the conditional expression. In other words, you can avoid the whole mess by steering clear of mixed-type computation.
2. If one of the operands is of type T where T is byte, short, or char and the other operand is a constant expression of type int whose value is representable in type T, the type of the conditional expression is T.
3. Otherwise, binary numeric promotion is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.

So now lets see the first expression:

System.out.print(true ? x : 0);
Here first operand is char, and second operand is constant so 2nd point will apply...so type will remain T..i.e. char...so right output is printed.

Consider the second case:

System.out.print(false ? i : x);
Here first operand is integer variable and second operand is character, so argument 3 will hold....so char is promoted to int and ascii value of char is printed.

Making it print XX will only take to make i as final.
final int i = 0;


Why swap with xor works fine in c++ but in java doesn't ?

Look at the following java snippet:
int x=1;
int y=2;
x ^= y ^= x ^= y;

I am expecting the values to be swapped.But it gives x=0 and y=1. when i tried in C / CPP language it gives the correct result.

So what is the reason...lets look at it:
x = x ^ (y = y ^ (x = x ^ y));

Unlike in C, in Java the left operand of a binary operator is guaranteed to be evaluated before the right operand. Evaluation occurs as follows:
x = x ^ (y = y ^ (x = x ^ y))
x = 1 ^ (y = 2 ^ (x = 1 ^ 2))
x = 1 ^ (y = 2 ^ (x = 3))
x = 1 ^ (y = 2 ^ 3)             // x is set to 3 
x = 1 ^ (y = 1)
x = 1 ^ 1                       // y is set to 1
x = 0                           // x is set to 0

You could reverse the order of the arguments to each xor expression so that the assignment is done before the variable is evaluated again:
x = (y = (x = x ^ y) ^ y) ^ x
x = (y = (x = 1 ^ 2) ^ y) ^ x
x = (y = (x = 3) ^ y) ^ x 
x = (y = 3 ^ y) ^ x             // x is set to 3
x = (y = 3 ^ 2) ^ x
x = (y = 1) ^ x
x = 1 ^ x                       // y is set to 1
x = 1 ^ 3
x = 2                           // x is set to 2
This is a more compact version that also works:
x = (y ^= x ^= y) ^ x;

But this is a truly horrible way to swap two variables. It's a much better idea to use a temporary variable.
int t = a;
a = b;
b = t;

Also, the xor logic will work, if we have 3 separate statement
a ^= b; 
b ^= a;
a ^= b;


Monday, 16 January 2012

Long division in java (for large numbers)

class LongDiv{
public static void main(String [] args){

    final long x = 24*60*60*1000*1000;
    final long y = 24*60*60*1000;
    System.out.println(x/y);
}
}


although the expected answer is 1000, but the javac gives it as 5. Reason?

Solution:
This happens because / is int operator, so large values while division are converted to integer and overflow happens. So to stop this "silent overflow" we have to use literal L to stop it.
final long x = 24L*60L*60L*1000L*1000L;
final long y = 24L*60L*60L*1000L;
System.out.println(x/y);



The x you computed, in the integer range, was 500654080. This divided by the y ( = 86400000), results in 5.794607407407407.... Java truncates the decimal part which causes the 5.

By adding an L after the number literal, you tell the compiler to compile it as a long instead of an int. The value for x you expected is 86400000000. But is was compiled as an int.

We can reproduce the wrong value for x (500654080) by truncating it to an int:
// First correct
long x = 24L*60L*60L*1000L*1000L;
/* x = `86400000000`; */
// Now truncate
x &= 0xFFFFFFFFL; // again: don't forget the L suffix
/* x = `500654080` */

Some languages don't do this, but support target typing, a language feature wherein the type of the variable in which a result is to be stored influences the type of the computation.