Exercise: Rudimentary Calculator

Exercise 4 Easy

Prerequisites for the exercise

  1. PHP Control Flow
  2. All previous chapters

Objective

Extend the program created in the previous Addition Calculator exercise to perform any given operation on the input numbers, not just addition.

Description

Back in the Addition Calculator exercise, we created a program to add two input numbers.

Now you need to extend that program and perform any given operation on the two input numbers, other than just addition. The desired operation is itself specified as an input value.

As before, we begin with asking the user to enter two numbers, and then ask for the desired operation.

Shown below is the general form of the initial three input prompts of the program:

x: <input>
y: <input>
Operation: <operation>

Where <input> denotes a number and <operation> denotes a letter to specify the operation desired to be performed on x and y. <operation> must be one of the following characters:

  1. a for addition.
  2. s for subtraction.
  3. m for multiplication.
  4. d for division.
  5. e for exponentiation.
  6. r for remainder.

Finally, when all of the inputs are received, the program should output the following after leaving a blank line, if the given operation character was one of those mentioned above:

<x> <operation_symbol> <y> = <result>

where <x> and <y> are the input numbers x and y respectively, <operation_symbol> is the symbol to denote the corresponding operation in PHP, and <result> is the result of the operation (as performed on x and y).

If the input operation character wasn't one of those mentioned above, then the program should simply output the text 'Unknown operation.', once again with a blank line before itself.

Shown below is an example:

x: 10
y: 20
Operation: a

10 + 20 = 30

Here's another example:

x: 50
y: 7
Operation: m

50 * 7 = 350

And yet another example:

x: 100
y: 8
Operation: b

Unknown operation.

Take note of the blank line after the Operation: ... prompt in all these examples. Your code must produce this blank line.

View Solution

New file

Inside the directory you created for this course on PHP, create a new folder called Exercise-4-Rudimentary-Calculator and put the .php solution files for this exercise within it.

Solution

We start off by obtaining the three desired inputs by printing the respective prompt messages:

<?php

echo 'x: ';
$x = (int) fgets(STDIN);

echo 'y: ';
$y = (int) fgets(STDIN);

echo 'Operation: ';
$op = rtrim(fgets(STDIN));

Next up, we check which letter did the user enter in the last input prompt i.e. the value of $op, and then based on it, make the respective output. This is done using the if, elseif and else statements.

Consider the following code:

<?php

echo 'x: ';
$x = (int) fgets(STDIN);

echo 'y: ';
$y = (int) fgets(STDIN);

echo 'Operation: ';
$op = rtrim(fgets(STDIN));

// Blank line.
echo "\n";

if ($op == 'a')
   echo $x, ' + ',  $y, ' = ', $x + $y;

elseif ($op == 's')
   echo $x, ' - ',  $y, ' = ', $x - $y;

elseif ($op == 'm')
   echo $x, ' * ',  $y, ' = ', $x * $y;

elseif ($op == 'd')
   echo $x, ' / ',  $y, ' = ', $x / $y;

elseif ($op == 'r')
   echo $x, ' % ',  $y, ' = ', $x % $y;

elseif ($op == 'e')
   echo $x, ' ** ', $y, ' = ', $x ** $y;

else
   echo 'Unknown operation.';

The statement in line 11, for the case when $op is equal to 'a', is simply making an output in the format specified in the exercise's description above. The same goes for the rest of the output statements.

And with this, our exercise completes.

DRY — Don't Repeat Yourself

When programming, there is one principle to always keep in mind — the DRY principle.

DRY stands for Don't Repeat Yourself, and is fairly self-explanatory. It says that you should not repeat yourself — or better to say, you should not repeat code.

In the last code snippet above, notice that we are merely repeating the echo statement over and over again, with just changing the symbol for the operation and the actual expression to be computed.

Imagine if we had to change the output made in each case. For example, let's suppose, we had to print the following:

The result: <result>

where <result> denotes the result of performing the respective operation on x and y.

Shown below is an example:

x: 50
y: 7
Operation: m

The result: 350

To account for this change in the output value, we'd need to change each print() statement in our original code.

Doesn't this sound quite inefficient?

Well, it sure does. That's because we are repeating a lot in our code.

Following DRY, we must keep from repeating unwanted statements in our code, and rather replace them with statements that could ultimately enable us to make small changes (such as changing the output in the case above) in the code very easily.

So coming back to our code, we could do one very basic change to it in order to make it much much more flexible.

Let's see that:

<?php

echo 'x: ';
$x = (int) fgets(STDIN);

echo 'y: ';
$y = (int) fgets(STDIN);

echo 'Operation: ';
$op = rtrim(fgets(STDIN));

// Blank line.
echo "\n";

if ($op == 'a') {
   $op_sym = '+';
   $result = $x + $y;
}
elseif ($op == 's') {
   $op_sym = '-';
   $result = $x - $y;
}
elseif ($op == 'm') {
   $op_sym = '*';
   $result = $x * $y;
}
elseif ($op == 'd') {
   $op_sym = '/';
   $result = $x / $y;
}
elseif ($op == 'r') {
   $op_sym = '%';
   $result = $x % $y;
}
elseif ($op == 'e') {
   $op_sym = '**';
   $result = $x ** $y;
}

Instead of directly making an output in each conditional's body, we now create two variables: $op_sym holding the symbol of the operation, and $result holding the result of the operation.

Once these variables have been created by any of the conditional statements, we make the desired output using $x, $op_sym, $y and $result.

However, if these two variables aren't created, that simply means that none of the conditions were met and hence we should output 'Unknown operation.'.

And that's it.

Here's the complete code:

<?php

echo 'x: ';
$x = (int) fgets(STDIN);

echo 'y: ';
$y = (int) fgets(STDIN);

echo 'Operation: ';
$op = rtrim(fgets(STDIN));

// Blank line.
echo "\n";

if ($op == 'a') {
   $op_sym = '+';
   $result = $x + $y;
}

// ...

if (isset($op_sym))
   echo $x, ' ', $op_sym, ' ', $y, ' = ', $result;
else
   echo 'Unknown operation.';

Time to clarify one thing...

Applying DRY doesn't always lead to shorter code. The principle just states not to repeat statements that shouldn't be repeated — while achieving this, we might end up adding more code, but that's perfectly alright.

Yes, sometimes we could move on with inflexible, repetitive pieces of code, as in the first solution above where we had multiple echo statements. This usually happens in personal projects, or in competitive programming, where we are just concerned with the output of the program and not with development of the program in the future.

But, when we work in large teams where multiple programmers collaborate on the same pieces of code, having repetitive stuff can not only make your work unpresentable, but also unprofessional.

To boil it down, being able to produce DRY code is surely a paramount skill for a programmer to have, and as with many skills, it comes with time and experience.