Program: Room Dimensions

Let’s write a program to see some of the advantages that variables bring. Imagine that we are standing in a rectangular room with a length of 7m and a width of 9m. We want to know the area of the floor, which is simply length multiplied by width. Of course, we can work this out in our heads but if ever the numbers are more complicated, we’ll be glad to have a program that can calculate it for us.

First Steps

To find out the area of the room, we could shamelessly multiply the two numbers in a print statement like so:

public static void main(String[] args) {
   System.out.println(7 * 9);
}
[Output]
63

That works, the area is 63m2. Now we decide we want to know the perimeter as well. The perimeter is all four sides added together. Since the room is rectangular, opposite sides will be the same length. Therefore, we can calculate the perimeter as shown (highlighted lines indicate code that has been added/modified):

public static void main(String[] args) {
    System.out.println(2 * 7 + 2 * 9);
    System.out.println(7 * 9);
}
[Output]
32
63

So, the perimeter is 32m and area is 63m2. However, I foresee problem with our approach. We might want to know even more information such as the volume of the room and the length from one corner to another corner. Also, what if we also want to do these calculations for ten or even a hundred rooms of all different sizes? For each room we would have to replace all the numbers in every expression and it would soon become very tedious. This is where variables can help. Above the print statements we’ll declare two variables called l and w (for length and width). We’ll set l to 7 and w to 9.

public static void main(String[] args) {
   double l = 7;
   double w = 9;

   System.out.println(2 * 7 + 2 * 9);
   System.out.println(7 * 9);
}

Then we’ll replace the numbers in the print statements with the two variables.

public static void main(String[] args) {
   double l = 7;
   double w = 9;

   System.out.println(2 * l + 2 * w);
   System.out.println(l * w);
}

If we run the program again, we’d get the same result, but this time we’re storing the length and width in variables (lines 2 and 3) and using the variables in the expressions (lines 5 and 6) instead of hard-coding the numbers. This is great as it stops us from having to change all the numbers by hand. Now if we want to know the measurements of a different room, we can just change the values of the variables and run the program again. For example, a room with length 12.03m and width 8.61m:

public static void main(String[] args) {
   double l = 12.03;
   double w = 8.61;

   System.out.println(2 * l + 2 * w);
   System.out.println(l * w);
}
[Output]
41.28
103.57829999999998

Perimeter is 41.28m and area is 103.5783m2. So far so good but, already, there are several changes we can make to the code for a cleaner and more readable program, in terms of both the output and the code itself.

Variable Naming

Currently the variables are named l and w, and, while these aren’t bad names, it’s often better to give variables names that clearly convey what the variable stands for. Therefore, we’ll change them to length and width since this is clearer than just single letters. But changing the name of a variable means we have to change all the places the variable is used. This is tedious and quickly becomes impractical as the program gets larger, which is why most IDEs have this functionality built in. For example, to rename variable w, simply right-click it, go to Refactor > Rename, type width, and press enter. You should see that the variable is now called width and all the places it’s used/referenced have been updated as well. We can also change l to length using the same method.

public static void main(String[] args) {
   double length = 12.03;
   double width = 8.61;

   System.out.println(2 * length + 2 * width);
   System.out.println(length * width);
}

Variable Versatility

It’s often a good idea to store the result of expressions in variables, even if we only use them once. For example, in the code above on line 5, the perimeter is calculated directly in the print statement. Let’s instead take that expression out of the print statement and place it in a variable:

public static void main(String[] args) {
   double length = 12.03;
   double width = 8.61;
  
   double perimeter = 2 * length + 2 * width;

   System.out.println(perimeter);
   System.out.println(length * width);
}

On line 5, there is now a variable called perimeter and the result of the expression is stored in this variable. Then the variable is simply printed on line 7. This may seem pointless because before we were printing the result of the expression directly, and now we’re storing the result in a variable and then printing the variable, but it’s beneficial if we need to use the perimeter in several places because variables are reusable. Plus, a variable gives a human-readable name to the result that we can quickly understand. In other words, seeing perimeter is better than just seeing 2 * length + 2 * width.

Now let’s do the same thing with the area. We simply declare another variable called area. Then move the expression out of the print statement and into area. Then print area.

public static void main(String[] args) {
   double length = 12.03;
   double width = 8.61;

   double perimeter = 2 * length + 2 * width;
   double area = length * width;

   System.out.println(perimeter);
   System.out.println(area);
}

Labelling the Output

It’s not clear just from looking at the output what the numbers mean. Let’s label them by concatenating (joining) some text to the beginning.

public static void main(String[] args) {
   double length = 12.03;
   double width = 8.61;

   double perimeter = 2 * length + 2 * width;
   double area = length * width;

   System.out.println("Perimeter: " + perimeter);
   System.out.println("Area: " + area);
}
[Output]
Perimeter: 41.28
Area: 103.57829999999998

On line 8, the plus symbol (+) is used to concatenate (join) the string “Perimeter: ” with the variable perimeter. This will combine the two into a single string, which is then printed, resulting in the output as shown. Line 9 does the same thing but with the area.

Note
The + is overloaded, meaning it has different behaviour based on the context in which it’s used. It is the addition operator when used with two numbers e.g. 10 + 35 = 45. When a string is involved, it is the concatenation operator e.g. 10 + “lemon” = “10lemon”.

Introducing System.out.printf

There is a glaring issue of numbers being printed in their fullest light. This is one of the drawbacks of using floating-point data types such as double. We want to round these numbers to 2 or 3 decimal places before they are printed so we don’t get overly long output values such as 103.578299999… For this, we have to use a different printing method called printf (print formatted), which allows us to format data in various ways for printing. Let’s look at an example of printf:

System.out.printf("I want %d cakes.", 5);

We can see between the parentheses is a string that reads “I want %d cakes.” This is followed by an integer, 5. The two values are separated by a comma. What happens is Java will replace the %d in the string with 5, therefore the output will be:

[Output]
I want 5 cakes.

To elaborate, we are passing two values to printf, the first is the string “I want %d cakes.” and the second is the integer 5. In general, a value that is passed to a method via the parentheses is called an argument. Commas are used to separate multiple arguments. So “I want %d cakes.” and 5 are two arguments being passed into printf. In the string, the %d acts as a placeholder for subsequent arguments, therefore the 5 takes the place of the %d and the resultant string is “I want 5 cakes.”.

The %d is a format specifier i.e. it specifies how data should be formatted. %d is specifically for (decimal) integers, which is why we are using %d since 5 is an integer. Let’s see what happens if we pass in a third argument, like 12:

System.out.printf("I want %d cakes.", 5, 12);

The 12 will be ignored since there’s only one %d in the string to be replaced. So, let’s add another:

System.out.printf("I want %d cakes and %d pizzas.", 5, 12);

Each %d always gets replaced in the same order that they and the arguments appear. So, the first %d will be replaced with 5 and the second %d will be replaced with 12.

[Output]
I want 5 cakes and 12 pizzas.

Because %d is only for integers, changing the 5 to 5.5 won’t work unless we also change the format specifier from %d to %f (for floating-point number):

System.out.printf("I want %f cakes and %d pizzas.", 5.5, 12);

The %f should be replaced with 5.5 and %d replaced with 12:

[Output]
I want 5.500000 cakes and 12 pizzas.

As we can see the %f gets replaced not with 5.5, but 5.500000. This is because %f will round the number to 6 decimal places as part of its default formatting behaviour. To round to 1 decimal place, we need to put .1 in the middle of %f like this:

System.out.printf("I want %.1f cakes and %d pizzas.", 5.5, 12);
[Output]
I want 5.5 cakes and 12 pizzas.

The .1 tells it to round the number to 1 decimal place, hence we get 5.5. If we put %.2f, it would round to 2 decimal places to get 5.50. If we put %.3f it would round to 3 decimal places for 5.500, and so on. What about a placeholder for strings? For that we use %s. Let’s replace the word “cakes” with %s and insert another argument that reads “cookies”:

System.out.printf("I want %.1f %s and %d pizzas.", 5.5, "cookies", 12);

The %f gets replaced with 5.5, the %s gets replaced with “cookies”, and the %d gets replaced with 12, resulting in:

[Output]
I want 5.5 cookies and 12 pizzas.

Note
Along with System.out.printf, there’s also System.out.format. They work exactly the same way; it just depends on which one you like the look of more.

Let’s now apply System.out.printf to our program:

public static void main(String[] args) {
   double length = 12.03;
   double width = 8.61;

   double perimeter = 2 * length + 2 * width;
   double area = length * width;

   System.out.printf("Perimeter: %.2f\n", perimeter);
   System.out.printf("Area: %.2f\n", area);
}
[Output]
Perimeter: 41.28
Area: 103.58

On line 8, in the string, %.2f will be replaced with perimeter (41.28). It will be rounded to two decimal places due to the .2. In this case, the number 41.28 already matches this criterion so it is printed as normal. On line 9, the same thing happens with the area. Variable area contains 103.57829999… and rounded to two decimal places gives 103.58 as the output. Also notice that a \n is needed at the end of each string because printf does not put newlines at the end automatically unlike println.

The Volume of a Room

To calculate the volume of the room requires an additional measurement—the height—since volume is length * width * height. All in all, it’s pretty straightforward:

public static void main(String[] args) {
   double length = 12.03;
   double width = 8.61;
   double height = 2.47;

   double perimeter = 2 * length + 2 * width;
   double area = length * width;
   double volume = length * width * height;

   System.out.printf("Perimeter: %.2f\n", perimeter);
   System.out.printf("Area: %.2f\n", area);
   System.out.printf("Volume: %.2f\n", volume);
}
[Output]
Perimeter: 41.28
Area: 103.58
Volume: 255.84

Lines 4, 8, and 12 are new. Line 4 declares a height variable. Line 8 calculates the volume (length * width * height) and stores the result in volume. Line 12 prints the volume in the same fashion as the other two measurements.

Sprucing up the Program

Let’s make the program a little more interesting and informative with some more changes.

Adding a Title

First, we’ll add a title to the top:

public static void main(String[] args) {
   System.out.println("- ROOM INFO -\n");

   double length = 12.03;
   double width = 8.61;
   double height = 2.47;

   ...
[Output]
- ROOM INFO -

Perimeter: 41.28
Area: 103.58
Volume: 255.84

On line 2, the text “- ROOM INFO -” is printed, which simply results in that text appearing at the top of the program when it is run.

Output the Input

Let’s print the variables length, width, and height back out just to reassure the user that the program is working with the correct numbers. We can do this all on one line if necessary:

public static void main(String[] args) {
   System.out.println("- ROOM INFO -\n");

   double length = 12.03;
   double width = 8.61;
   double height = 2.47;

   System.out.printf("Length: %.2fm\nWidth: %.2fm\nHeight: %.2fm\n\n", length, width, height);

   double perimeter = 2 * length + 2 * width;
   ...
[Output]
- ROOM INFO –

Length: 12.03m
Width: 8.61m
Height: 2.47m

Perimeter: 41.28
Area: 103.58
Volume: 255.84

On line 8, a print statement has been added that prints out the length, width and height. The line of code itself may look confusing but take some time to study it and compare it with the output. To help, here is the code and the output with corresponding parts highlighted to distinguish them.

System.out.printf("Length: %.2fm\nWidth: %.2fm\nHeight: %.2fm\n\n", length, width, height);
[Output]
Length: 12.03m
Width: 8.61m
Height: 2.47m

Highlighted in orange are all the format specifiers. The rest, highlighted in green, is plain text and gets printed normally. The newlines I’ve left unhighlighted. If we continuously compare the code with the output, we can follow it in order:

  • First, the text “Length: ” (in green) is printed.
  • Then comes “%.2f” (in orange). This will be replaced with the variable length, so 12.03 is printed.
  • Next the letter “m” (in green) is printed (since we’re working in metres).
  • Next is a “\n” for a newline, ensuring any consecutive text goes onto the next line.
  • After this, the width and height are handled in exactly the same way.

Improving the Output

The results should also have the correct units of measurement after them. For example, the area should have m2 after it for metres-squared. An easy way to get the 2 symbol (superscript 2) is to use Unicode. To use Unicode in Java, you start with \u and then a hexadecimal number. The hex number for a 2 is 00B2. Therefore writing \u00B2 in a string will cause a 2 to be outputted. Here it is in action:

System.out.printf("Perimeter: %.2f\n", perimeter);
System.out.printf("Area: %.2fm\u00B2\n", area);
System.out.printf("Volume: %.2f\n", volume);
[Output]
Perimeter: 41.28
Area: 103.58m2
Volume: 255.84

On line 2, the text m\u00B2 correctly outputs m2. Let’s also do the same for the perimeter and volume. Perimeter is easy, it’s just m (metres), but volume is m3 (metres-cubed). The hex number for 3 is 00B3. Here is the updated code:

System.out.printf("Perimeter: %.2fm\n", perimeter);
System.out.printf("Area: %.2fm\u00B2\n", area);
System.out.printf("Volume: %.2fm\u00B3\n", volume);
[Output]
Perimeter: 41.28m
Area: 103.58m2
Volume: 255.84m3

Now all three measurements display the correct units.

Adding Descriptive Comments

Comments can be written to help us remember what certain code does. Below are some examples of comments.


A comment that describes the three lines of code that prints the length, width, and height:

// Print out the room’s length, width, and height
System.out.printf("Length: %.2fm\n", l);
System.out.printf("Width: %.2fm\n", w);
System.out.printf("Height: %.2fm\n\n", h);

Comments can be added to the end of the line instead of above it:

double perimeter = 2 * l + 2 * w; // Calculate the perimeter

A multiline comment (/* */) that can span multiple lines:

/*
   Todo: Modify the program to enable input while it’s running
   Note to user: modify these three variables and run the program
*/
double l = 12.03;
double w = 8.61;
double h = 2.47;

Comments for remembering details:

System.out.printf("Perimeter: %.2fm\n", perimeter);
// \u00B2 is Unicode for power of 2 symbol
System.out.printf("Area: %.2fm\u00B2\n", area);
// \u00B3 is Unicode for power of 3 symbol
System.out.printf("Volume: %.2fm\u00B3%n", volume);

Feel free to add comments where it might help you to remember details. Just don’t go overboard as they can clutter the code.

Length from A to C

We want to know the distance from one corner of the floor to the opposite corner of the floor. This will require a square root operation. Java has a class called Math that contains many methods for performing mathematical operations, such as those you find on a calculator. One such method is sqrt (short for square root). Here is an example:

double result = Math.sqrt(9);

On the right side of the equals, the sqrt method of the Math class is called. Between the parentheses it takes one argument, a double. 9 is passed, which is an int, not a double, but Java will implicitly cast it to a double so this isn’t a problem.

Math.sqrt will calculate the square root of 9 and then return (pass back) the result. How do we retrieve the result? By assigning a variable to the call itself. In this case, a variable named result is assigned to the call and will therefore receive the returned value. In short, Math.sqrt(9) will calculate the square root of 9, which is 3. It will then return 3, which will be stored in variable result.

Note
The concept of calling methods for them to do work and then return a result is an important one. It is fundamental to the way complex programs are constructed.

Since we can form a right-angle triangle with ABC we can use Pythagoras’ theorem:

a2 + b2 = c2

where c is the hypotenuse, a is the length, and b is the width. We can rearrange for

c = √(a2 + b2)

In code it may look like this:

c = Math.sqrt(a * a + b * b); // assuming a, b, and c are declared variables

This is how we can calculate it for our program:

public static void main(String[] args) {
    System.out.println("- ROOM INFO -\n");

    double length = 12.03;
    double width = 8.61;
    double height = 2.47;

    System.out.printf("Length: %.2fm\nWidth: %.2fm\nHeight: %.2fm\n\n", length, width, height);

    double perimeter = 2 * length + 2 * width;
    double area = length * width;
    double volume = length * width * height;
    double lengthAC = Math.sqrt(length * length + width * width);

    System.out.printf("Perimeter: %.2fm\n", perimeter);
    System.out.printf("Area: %.2fm\u00B2\n", area);
    System.out.printf("Volume: %.2fm\u00B3\n", volume);
    System.out.printf("Length from A to C: %.2fm", lengthAC);
}
[Output]
- ROOM INFO -
 
Length: 12.03m
Width: 8.61m
Height: 2.47m
 
Perimeter: 41.28m
Area: 103.58m²
Volume: 255.84m³
Length from A to C: 14.79m

Line 13 is where the calculation is performed. In the parentheses the expression

length * length + width * width

is calculated resulting in 218.853. This number is passed to Math.sqrt, which returns the square root (14.7936…). This number gets stored in variable lengthAC. On line 18, lengthAC is printed.

Leave a Reply

Your email address will not be published. Required fields are marked *