## Operators and expressions

No. 34

### Expressions and type

Q:

Consider the following code segment:

short a = 4; ❶
short sum = a + 7; ❷
 Declaring a short variable a assigning 4. Declaring a short variable sum assigning 4 + 7.This yields a compile time error: Type mismatch: cannot convert from int to short

On contrary the following line will compile flawlessly:

short sum = 4 + 7;

Explain this strange behaviour.

A:

The expression a + 7 contains a variable a of type short to the plus operator's left and an int literal 7 to its right. Thus the plus operator yields an int result (the biggest type of both operands) which cannot be assigned to the variable sum of type short.

The very same argument seems to apply for the expression 4 + 7 even more: This time the plus operator acts on even two int operands. However in contrast to the former assignment this time both operands are static. The 4 + 7 expression's value of 11 is being calculated at compile time. Since 11 of type int is within $[ - 2 15 , - 2 15 - 1 ]$ the compiler will safely cast this value to the short variable sum without information loss.

No. 35

### Dividing values

 Q: Consider the following statement:System.out.println(8 / 9);The output is 0 rather than 0.888888... . Explain this result. A: The divide operator acts on two int literal values 8 an 9. Thus irrespective of the possibly intended floating point result the resulting type is int . According to https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3-300-A-2 the floating point value 0.88888... will be “rounded toward zero” yielding an int value of 0 rather than 1.

No. 36

### Strange things happen

Q:

1. Consider the following code snippet:

byte a = 127;
System.out.println("Current value=" + a + ", now adding 1 to it");
a++;
System.out.println("New value=" + a);

This will produce the following output:

Current value=127, now adding 1 to it
New value=-128

Explain this strange behaviour on bit level.

2. Moreover the following yields a compile time error:

byte a = 127;
System.out.println("value=" + a);
a = a + 1; // Error: Type mismatch: cannot convert from int to byte
System.out.println("New value=" + a);

What do you learn about the two operators + an a++? Explain this error's cause.

### Tip

You may want to read the overview section on statements in [Kurniawan].

A:

1. A byte variable ranges from -128 to +127. Thus incrementing 127 by 1 yields -128 and thus an overflow error.

Since Java uses Two's complement representation we have:

  01111111  127 +00000001  +1 =10000000 =-128

On machine level the above calculation is just an ordinary addition.

Conclusion: Watch out when doing (integer) arithmetic!

2. The compile time error is due to the definition of the + operator in Java always returning an int rather than a byte. Consider:

byte a = 120, b = 10;
System.out.println(a + b);

This yields the expected output of 130 and corresponds to an int value.

If the expression a + b was of data type byte in Java an arithmetic overflow as in the subsequent code example would occur:

byte a = 120, b = 10;

byte sum = (byte) (a + b);

System.out.println(sum);

The explicit type conversion (a so called type cast or cast for short) forces the 4-byte int into a one-byte variable sum thereby loosing its original value and returning -126 instead.

Conclusion: a = a + 1 and a++ (surprisingly) differ in behaviour when being applied to non-int variables.

No. 37

 Q: Consider the following code:System.out.println(2147483647 + 1); System.out.println(2147483647 + 1L);This yields:-2147483648 2147483648Explain this result. Please refrain from answering “Thats what bankers do!” A: The value 2147483647 is actually the largest possible int value Integer.MAX_VALUE. The plus operator in the first expression 2147483647 + 1 acts on two operands of type int. Thus the resulting sum will be of type int as well irrespective of its value. On binary level adding an int value of 1 results in:  01111111_11111111_11111111_11111111 2147483647 + 00000000_00000000_00000000_00000001 + 1 ------------------------------------- ------------ 10000000_00000000_00000000_00000000 -2147483648With respect to two-complement representation of signed int values this is actually an overflow error: There simply is no positive int value of 2147483648 in Java™. See http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3-220 for details. On contrary the plus operator in the expression 2147483647 + 1L acts on an int to its left and a long to its right. The result will thus be of type long:  01111111_11111111_11111111_11111111 2147483647 + 00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001 + 1 ------------------------------------------------------------------------- ------------ 00000000_00000000_00000000_00000000_10000000_00000000_00000000_00000000 2147483648Due to a long's larger allocation of eight rather than four bytes execution reveals no overflow problem thus yielding the expected result.

No. 38

### Representational float and double miracles

Q:

Consider and execute the following code snippet:

public static void main(String[] args) {
final double a = 0.7;
final double b = 0.9;
final double x = a + 0.1; // 0.8
final double y = b - 0.1; // 0.8
System.out.println(x == y);
}

Which outcome do you expect? Explain the execution's result and propose a solution.

### Tip

You will have to replace the == operator by something more appropriate addressing limited arithmetic precision.

A:

The expression x == y evaluates to false. This surprising result is due to limited precision regarding both float and double IEEE representations: A given value will be approximated as close as possible.

Adding System.out.println(x - y) yields a value of -1.1102230246251565E-16 denoting the representational deviation of x and y.

Comparing float and double values thus requires providing a representational distance limit below which two values will be regarded as equal:

final double a = 0.7;
final double b = 0.9;
final double x = a + 0.1;
final double y = b - 0.1;
System.out.println(Math.abs(x - y) < 1.E-14);

The last line represents the boolean expression $| x - y | < 10 - 14$. So two values will be regarded as equal if their mutual distance is less than 0.00000000000001.

No. 39

### Expressions involving infinity

 Q: Figure 145, “Dividing by zero ” raises some interesting questions: What happens if we add e.g. 1000 to a variable containing a value of Infinity? What happens if we add or subtract two variables both containing a value of “Infinity”? A: double f = 1. / 0; double difference = f - 1000; System.out.println("Difference: " + difference);Difference: Infinity double f = 1. / 0; double g = 1. / 0; double difference = f - g; System.out.println("Difference: " + difference);Difference: NaNExplanation: This represents a special “not a number” encoded value.

No. 40

### Calculating a circle's area

Q:

The area $a$ of a given circle having radius $r$ is being obtained by $a = π × r 2$. Complete the following code to calculate the result and write it to standard output using System.out.println(...):

public static void main(String[] args) {

double radius = 2.31;   // A circle having a radius (given e.g. in mm).
double pi = 3.1415926;  // Constant relating a circle's radius,
//perimeter and area.

System.out.println( /* TODO: Write the circle's area to standard output */);
}

### Tip

You may want to read the overview section on statements in [Kurniawan].

A:

Using a mere expression
public static void main(String[] args) {

double radius = 2.31;   // A circle having a radius (given e.g. in mm).
double pi = 3.1415926;  // Constant relating a circle's radius,
//perimeter and area.

}
Using a variable

Instead of immediately using the expression as an argument to System.out.println(...) we may assign its value to a variable prior to output creation:

public static void main(String[] args) {

double radius = 2.31;   // A circle having a radius (given e.g. in mm).
double pi = 3.1415926;  // Constant relating a circle's radius,
//perimeter and area.

System.out.println(area);
}

No. 41

### Calculating the area of a circle avoiding accidental redefinition

Q:

In Exercise Calculating a circle's area you calculated a given circle's area:

public static void main(String[] args) {

double radius = 2.31;   // A circle having a radius (given e.g. in mm).
double pi = 3.1415926;  // Constant relating a circle's radius, perimeter
//and area.

System.out.println(area);
}

Though there is nothing wrong with this approach it is error prone: In a similar program a careless programmer accidentally redefine the value of pi:

double pi = 3.141592653589793;

double radius = 2.3; // Computing a circle's area
System.out.println("A circle of radius " + radius + " will cover an area of " +

pi = -4; // Woops, accidential redefinition

System.out.println("A circle of radius " + radius + " will cover an area of " +
pi * radius * radius);

Modify the above code to avoid this type of error.

### Tip

A:

The solution is straightforward. We just add a final modifier to the definition of our variable pi:

final ❶ double pi = 3.141592653589793;
...
pi = -4; ❷
...
 A final modifier prohibits subsequent variable assignments thus keeping its initially assigned value constant. The assignment attempt is being flagged as a compile time error: Cannot assign a value to final variable 'PI'

As a rule of thumb: Whenever you intend a variable not to change after an initial assignment use final declaring it to remain constant.

In addition we may refactor our variable pi to use capital letters reflecting the naming convention for constants. This is does not change program execution in any way but enhances code readability:

final double PI = 3.141592653589793;
double radius = 2.3; // Computing a circle's area
System.out.println("A circle of radius " + radius + " will cover an area of " +

PI = -4;

System.out.println("A circle of radius " + radius + " will cover an area of " +
PI * radius * radius);

No. 42

### Turning weeks into seconds

 Q: Consider:final short weeks = 2, days = 3, hours = 14, minutes = 32, seconds = 55; final int secondsElapsed = ...; // TODO: assign elapsed seconds corresponding to previous time frame. System.out.println(secondsElapsed);Create an expression based on the variables weeks, days, hours, minutes and seconds to calculate the number of seconds elapsed for the given time period of two weeks, three days and so on. After you have completed this task read about Horner's rule and try to improve your solution with respect to execution time. A: A straightforward solution reads:final short weeks = 2, days = 3, hours = 14, minutes = 32, seconds = 55; final int secondsElapsed = seconds + 60 * minutes + 60 * 60 * hours + 60 * 60 * 24 * days + 60 * 60 * 24 * 7 * weeks; System.out.println(secondsElapsed);This requires four additions and 10 multiplications. We may use: ... final int secondsElapsed = seconds + 60 * (minutes + 60 * (hours + 24 * (days + 7 * weeks))); ...This leaves us with four additions but just 4 instead of 10 multiplications. Within the given context the difference in execution time can be neglected. But in a different application the calculation in question might have to be repeated millions of times giving rise to a substantial gain with respect to total execution time.

No. 43

### Turning seconds into weeks

Q:

This exercise is about reversing Turning weeks into seconds namely decomposing a given value of elapsed seconds into weeks, days, hours, minutes and seconds:

final int secondsElapsed = 1521175;

final int weeks = ...; // TODO
final int days = ...;// TODO
final int hours = ...;// TODO
final int minutes = ...;// TODO
final int seconds = ...;// TODO

System.out.println(weeks + ", " + days + ", " + hours + ", " + minutes + ", " + seconds);

### Tip

As an example consider decomposing 192 seconds into minutes and seconds:

• Integer division 192 / 60 seconds yields 3 minutes.

• We get the remaining seconds by virtue of the remainder operator 192 % 60.

Thus 192 seconds equal 3 minutes and 12 seconds

A:

We extend the given minute calculation example to all 5 desired values. For the sake of convenience the number of seconds per minute, per hour and so on are being calculated beforehand:

final int secondsElapsed = 1521175;

//
final int
secondsPerMinute = 60,                    // 60 minutes per hour
secondsPerHour =   60 * secondsPerMinute, // 3600 seconds per hour
secondsPerDay =    24 * secondsPerHour,   // 86400 seconds per day
secondsPerWeek =    7 * secondsPerDay;    // 604800 seconds per week

int remainingSeconds = secondsElapsed;

final int weeks = remainingSeconds / secondsPerWeek;
remainingSeconds = remainingSeconds % secondsPerWeek;

final int days = remainingSeconds / secondsPerDay;
remainingSeconds %= secondsPerDay;

final int hours = remainingSeconds / secondsPerHour;
remainingSeconds %= secondsPerHour;

final int minutes = remainingSeconds / secondsPerMinute;
remainingSeconds %= secondsPerMinute;

final int seconds = remainingSeconds;

System.out.println(weeks + ", " + days + ", " + hours + ", " + minutes + ", " + seconds);

No. 44

### Using predefined Java™ standard library constants

Q:

In the previous exercise we coded:

final double PI = 3.141592653589793;
double radius = 2.3; // Computing a circle's area
System.out.println("A circle of radius " + radius + " will cover an area of " +
PI * radius * radius);

Do we actually have to provide the value of pi (3.141592653589793) ourself?

### Tip

Consider the standard Math library.

A:

The solution is straightforward using Math.PI:

double radius = 2.3; // Computing a circle's area
System.out.println("A circle of radius " + radius + " will cover an area of " +
Math.PI * radius * radius);

No. 45

### Converting temperature values

 Q: Write an application converting temperature values being represented as degree centigrade to kelvin and Fahrenheit: public static void main(String[] args) { double temperatureCelsius = 23.2; ... System.out.println("Celsius: " + temperatureCelsius); System.out.println("Kelvin: " + temperatureKelvin); System.out.println("Fahrenheit: " + temperatureFahrenheit); } A: public static void main(String[] args) { double temperatureCelsius = 23.2; double temperatureKelvin = temperatureCelsius + 273.15, temperatureFahrenheit = 9 * temperatureCelsius / 5 + 32; System.out.println("Celsius: " + temperatureCelsius); System.out.println("Kelvin: " + temperatureKelvin); System.out.println("Fahrenheit: " + temperatureFahrenheit); }

No. 46

### Time unit conversion

Q:

This exercise consists of two parts:

1. Write an application converting a (seconds, minutes ,hours) time specification to seconds:

public static void main(String[] args) {

final int
seconds = 31,
minutes = 16,
hours = 4;

int timeInSeconds ...

System.out.println("Time in seconds:" + timeInSeconds);
}

Time in seconds:15391
2. Reverse the previous part of this exercise: Convert a time specification in seconds to (seconds, minutes ,hours) as in:

public static void main(String[] args) {

final int timeInSeconds = 15391;

...

System.out.println("Hours:" +  hours);
System.out.println("Minutes:" +  minutes);
System.out.println("Seconds:" +  seconds);
}

Hours:4
Minutes:16
Seconds:31

### Tip

Consider the remainder operator % (modulo operator).

A:

public static void main(String[] args) {

final int
seconds = 31,
minutes = 16,
hours = 4;

final int timeInSeconds = seconds + 60 * (minutes + 60 * hours);

System.out.println("Time in seconds:" + timeInSeconds);
}
2. public static void main(String[] args) {

final int timeInSeconds = 15391;

final int minutesRemaining = timeInSeconds / 60;
final int seconds = timeInSeconds % 60;

final int hours = minutesRemaining / 60;
final int minutes = minutesRemaining % 60;

System.out.println("Hours:" +  hours);
System.out.println("Minutes:" +  minutes);
System.out.println("Seconds:" +  seconds);
}

No. 47

### Interest calculation

Q:

We want to calculate the compounded interest starting from an initial capital, a given annual interest rate and a duration of three years. Consider the following code fragment:

public static void main(String[] args) {

final double initialCapital = 223.12;
final double interestRate = 1.5;

System.out.println("Initial capital:" + initialCapital);
System.out.println("Annual interest rate:" + interestRate);

// TODO ...

System.out.println("Capital after three years:" + ...);
}

The expected output is:

Initial capital:223.12
Annual interest rate:1.5
Capital after three years:233.31175902999993

### Tip

A:

We obtain the compounded interest by multiplying the initial capital by $1 + r / 100$ for each year where r represents the given interest rate.

Since we have not yet introduced loops this multiplication has to be repeated three times:

public static void main(String[] args) {

final double initialCapital = 223.12;
final double interestRate = 1.5;

System.out.println("Initial capital:" + initialCapital);
System.out.println("Annual interest rate:" + interestRate);

final double factor = 1. + interestRate/100.;
double capitalAtThreeYears = initialCapital;

capitalAtThreeYears *= factor; // Year 1
capitalAtThreeYears *= factor; // Year 2
capitalAtThreeYears *= factor; // Year 3

System.out.println("Capital after three years:" + capitalAtThreeYears);
}

We might as well use a single arithmetic expression to achieve the same result:

public static void main(String[] args) {

final double initialCapital = 223.12;
final double interestRate = 1.5;

System.out.println("Initial capital:" + initialCapital);
System.out.println("Annual interest rate:" + interestRate);

final double factor = 1. + interestRate/100.;
final double capitalAtThreeYears =
initialCapital * factor * factor * factor;

System.out.println("Capital after three years:" + capitalAtThreeYears);
}

In the section called “Interest calculations” we will present a more elaborate solution based on loops and class methods.

No. 48

### Summing short and char

Q:

Consider the following snippet:

short s = 1;
char c = 'A'; // ASCII 65
System.out.println(s + c);

Execution results in 66. What is the s+c expression's type?

### Tip

Try to assign the expression to another variable and experiment using type candidates. Try to make an educated guess explaining the result.

A:

Both short and char require two bytes in Java. It is thus surprising that a mixed expression has got neither of both input types:

short s = 1;
char c = 'A';
short resultShort = s + c; // Incompatible types Required: short found: int
char resultChar= s + c;    // Incompatible types Required: char found: int

According to the compiler's error message the expression s + c is of type int. Why choosing a result type being twice the size of both input types?

The two input types have different ranges:

short

Signed integer value ranging from $- 2 15$ to $2 15 - 1$.

char

Unsigned integer value ranging from 0 to $2 16 - 1$.

A promotion to int guarantees correct results in all circumstances.

No. 49

### Guessing results

Q:

Consider the following code segment:

int a = 3;
a++;          // Incrementing a by 1 --> a==4

int b = a;    // TODO

b--;          // TODO
--b;          // TODO

int c = b;    // TODO

b = ++a;      // TODO
int e = a++;  // TODO

a *= b;       // TODO

System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println("e=" + e);

We want to guess the expected result. Copy/paste the above code into a main() method body within your IDE of choice.

Do not execute this code yet but replace the TODO strings by guessing the respective variable's value beforehand as in line 2:

a=...

b=...

c=...

e=...

### Tip

Both x++ (postfix notation) and ++x (infix notation) are expressions themselves which might even be rewritten as (x++) and (++x) for the sake of clarity. The difference is not about operator precedence rules but simply about the values of these expressions when being assigned to other variables.

A:

As inferred by the hint the biggest problem is about understanding postfix and infix notation of the operators ++ and --. A corresponding expression evaluates to:

• a = x++ yields a ==x: The value of x before incrementing it.

• a = ++x yields a ==(x + 1): The value of x after incrementing it.

The rest is just obeying the due diligence rule set:

int a = 3;
a++;          //Incrementing a by 1 --> a==4

int b = a;    // Assigning value of a --> b==4

b--;          // Decrementing b by 1 --> b==3
--b;          // Decrementing b by 1 --> b==2

int c = b;    // c == 2;

b = ++a;      // Incrementing a by 1 -->a==5, then assigning to b --> b == 5
int e = a++;  // Assigning a to e --> e==5, then incrementing a --> a==6

a *= b;       // Multiplying a with b and assigning the result to a --> a==30

System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println("e=" + e);

No. 50

### Cleaning up the mess

Q:

Some developers follow the rule It was hard to write, it should be hard to understand as well. One such proponent codes:

int a = 3, b = 6, c = 2;

a += (a = 2) + ++a - ++b % c--;

System.out.println("a = " + a + ", b = " + b + ", c = " + c);

Execution results in:

a = 7, b = 7, c = 1

Decompose this cryptic assignment into a series of multiple elementary ones like e.g. a++ by possibly introducing one or more helper variables. Thus your code shall become longer but better to understand.

### Tip

A:

We start by modifying the line in question:

a = a + (a = 2) + ++a - ++b % c--;

The expression on the right hand side will be decomposed by the Java compiler into a sum of four subexpressions to be evaluated from left to right:

1. a

2. a=2

3. ++a

4. ++b % c--

This one deserves further attention: The % operator will act on b's value after incrementing (infix notation) and c's value before decrementing (postfix notation).

We introduce a helper variable sum for decomposing our code into the above described four subexpressions:

int a = 3, b = 6, c = 2;

int sum = a;  // First subexpression
a = 2;
sum += a;     // Second subexpression
a++;
sum += a;     // Third subexpression
b++;
sum -= b % c; // Fourth subexpression
c--;

a = sum;      // Assigning the result

System.out.println("a = " + a + ", b = " + b + ", c = " + c);