## Operators and expressions

No. 35

### int to short assignment

Q:

Consider the following code segment:

Figure 151. int expression assignment
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:

Figure 152. Constant expression assignment
short sum = 4 + 7;

Explain this strange behaviour.

A:

Considering short sum = 4 + 7 the plus operator acts on two int operands. Thus the expression 4 + 7 is of type int. Both operands are static i.e. their values are known at compile time (rather than at run time). The 4 + 7 expression's value can thus be evaluated at compile time. The resulting value of 11 is within $[ - 2 15 , - 2 15 - 1 ]$ so the compiler will safely cast and assign it to the variable sum of type short without any information loss.

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 expression is of type int as well. However a compiler will consider the variable a's value to be unknown within the given expression at compile time (albeit humans will safely assume a value of 4 by virtue of the preceding statement). Therefore variable a's value could potentially exceed a short's range of values and thus cannot be assigned to the variable sum in a safe manner.

No. 36

### int to short assignment using final

 Q: We reconsider a variant of Figure 151, “int expression assignment”: final short a = 4; short sum = a + 7;This time the code compiles flawlessly. Explain the underlying reason being related to the final modifier's role. A: A final variable's value cannot change. Thus the expression a + 7 is fully equivalent to 4 + 7 and can thus be evaluated at compile time. Like in the preceding Figure 152, “Constant expression assignment” code sample the resulting value of 11 neatly fits into the variable sum of type short.

No. 37

### 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. 38

### 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. 39

 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. 40

### 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. 41

### Expressions involving infinity

 Q: Figure 154, “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.

The careful reader may stumble upon the absence of e.g. a «+» operator turning two byte values a and b into an expression a + b of type byte rather than int. This is due to a Java Virtual Machine design decision leading to a limited set of computational types:

Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte. Instead, the instruction set of the Java Virtual Machine provides a reduced level of type support for certain operations. In other words, the instruction set is intentionally not orthogonal. Separate instructions can be used to convert between unsupported and supported data types as necessary.

No. 42

### 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. 43

### Calculating a circle's area 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: A careless programmer might 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 refactoring our variable pi using 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; // Compile time error

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

No. 44

### 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. Horner's rule allows for: ... final int secondsElapsed = seconds + 60 * (minutes + 60 * (hours + 24 * (days + 7 * weeks))); ...This still 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 larger application the calculation in question might have to be repeated millions of times giving rise to a substantial gain with respect to execution time.

No. 45

### 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. 46

### 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. 47

### 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. 48

### Time unit conversion

Q:

This is a two part exercise:

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. 49

### 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. 50

### 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. 51

### 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. 52

### 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);