Arithmetic Operations in JavaScript
In this, our second QuickStart tutorial, we’ll take a look at how we can use JavaScript to perform arithmetic calculations. We’ll also introduce how we can create our own functions that can be useful in various situations.
Learning Outcome Guide
At the end of this tutorial, you should be able to:
- Use arithmetic operators to perform numeric calculations
- Apply functions from the
Math
object for numeric calculations - Describe the situations in which JavaScript rounding errors occur with floating point calculations
- Resolve and correct rounding errors
- List five functions and two properties in the
Math
objecthypot()
,sin()
,cos()
,round()
,floor()
,ceil()
PI
,E
- Create a re-usable function using function declaration syntax
- Perform function calls on library functions (
Math
andconsole
) as well as developer-defined functions - Distinguish between declaring a function and invoking a function
- Describe the difference between arguments and parameters
- Convert numeric values to strings
.toFixed()
- Convert strings of digits into numeric values
parseFloat()
andparseInt()
- Distinguish between whole numbers and floating point numbers in JavaScript
Basic Math
Calculations are the life-blood of many applications, and every programming language supports a wide range of common calculations. Let’s explore with these steps.
-
Once again, launch VS Code side-by-side with an external terminal. This makes it easy to observe the output as we make changes to our JavaScript file. (See the first tutorial in this QuickStart series if you need a refresher on how to do this.)
-
Our last file was called
app.js
. Let’s create a new script file calledbasic-math.js
. You can place it in the same folder as the previous file. Again, we’ll use Node’s--watch
flag when we run the script in the terminal.basic-math.js console.log('My basic-math.js has loaded');Running from the same folder as basic-math.js node --watch basic-math.js -
Most math can be done with the built-in operators:
+
for addition,-
for subtraction,*
for multiplication, and/
for division.There’s also an operator to find the remainder of a division operation. It’s called the modulus operator, and the symbol is a percent sign:
%
. Here’s how that works.basic-math.js let answer = 23 % 10;console.log(`The remainder of 23 divided evenly by 10 is ${answer}.`);You should see the following output.
Terminal window The remainder of 23 devided evenly by 10 is 3 -
We can go a long way with just the basic math operators. Occasionally, however, we need to do complex math. One example is calculating a square root. Fortunately, there is a
Math
object in JavaScript that holds several useful functions for these situations.Let’s use it to find the hypotenuse of a right-angle triangle.
basic-math.js // Math function for the square rootlet adjacent = 4;let opposite = 3;let hypotenuse = Math.sqrt(adjacent**2 + opposite**2);message = `My triangle has sides of length ${adjacent}, ${opposite} and ${hypotenuse}.`;console.log(message); -
The Math library can also help us with rounding errors that sometimes occur. It might surprise you to discover that sometimes, JavaScript gets basic math wrong! Consider this example.
basic-math.js // Rounding errorslet floating = 0.1 + 0.2; // What's the answer?console.log(`0.1 + 0.2 is ${floating}`);Terminal window 0.1 + 0.2 is 0.30000000000000004Notce the output? JavaScript calculated the answer as
0.30000000000000004
. Don’t be too alarmed. These kinds of rounding errors are very rare, and they only occur for certain calculations involving a fractional or decimal portion to the number.Because all values in the computer are stored in binary (base-2) format instead of base 10, JavaScript has limits in how it can handle the precision of fractional portions of a number.
By the way, you will never have rounding errors with whole numbers!
-
We can fix rounding errors in a few ways. One approach is to use the
Math.round()
function. The only “gotcha” is that we need some rough idea of how many decimal places are “trustworthy” or accurate.In this case, it’s only one decimal place, so we’ll mutiply
floating
by 10, round the result, and then divide by 10 to get the right answer.basic-math.js answer = Math.round(floating * 10) / 10;console.log(`After rounding, the correct answer is ${answer}`); -
There are several functions in the
Math
object. You have ones for trigonometry (.sin()
,.cos()
, etc.) and rounding (.round()
,.floor()
,.ceil()
). There are constant values, such as the one for.PI
(much more precise than the few digits you might have memorized) and the one for Euler’s number (.E
).We could have even used the built-in function for calculating the hypotenuse:
Math.hypot()
. Here we are re-using our variables with different values.basic-math.js // Another triangleadjacent = 5;opposite = 12;hypotenuse = Math.hypot(adjacent, opposite);message = `My other triangle has sides of length ${adjacent}, ${opposite} and ${hypotenuse}.`;console.log(message);For more whole-number right-angle triangle sides, see this list.
That last function - Math.hypot()
- was a bit different than the others. Notice that within the parenthesis, we passed two values as a comma-separated list. Many functions exist that can accept more than one piece of information in order to do their job. We’ll explore a bit of this in the next part of this tutorial.
Our Own Functions
Having a library of functions like those in the Math
object is pretty useful, but eventually you will find yourself wishing you could create your own functions. Let’s grant that wish!
-
Remember that rounding problem we encountered earlier? We fixed it with some calculations and the
Math.round()
function.Wouldn’t it be nice if we could put all of that in its own function? We could even make it extra useful by letting us specify how many decimals we want to use in our rounding.
Add this code to your script.
basic-math.js // Declare our own functionfunction roundToDecimals(num, decimals) {let factor = Math.pow(10, decimals);return Math.round(num * factor) / factor;}This is a function declaration. We are saying, “Hey, I want to make a function called
roundToDecimals
. It will accept two values -(num, decimals)
- and it will do all the instructions inside the curly braces.”Declaring a function is where we decide exactly what instructions our function will perform. Once it is declared, we can then invoke or “use” the function by passing in some values.
-
First, let’s examine another known rounding error calculation.
basic-math.js // Another rounding error...console.log("Here's another rounding error:");console.log(`4.32 + 4.78 equals ${4.32 + 4.78}`);Here’s the output.
Terminal window 4.32 + 4.78 equals 9.100000000000001 -
Now, let’s use our
roundToDecimals()
function. We know that both of our values goes to two decimal’s worth of precision.basic-math.js // Use our custom functionconsole.log("Let's fix the calculation:");floating = 4.32 + 4.78;answer = roundToDecimals(floating, 2);console.log(`4.32 + 4.78 equals ${answer}`);Now our result is more accurate.
Terminal window 4.32 + 4.78 equals 9.1 -
We don’t have to restrict our use of
roundToDecimals()
to situations where there are rounding errors. We can use it for other purposes as well.basic-math.js console.log(`PI is ${Math.PI}`);console.log(`I find ${roundToDecimals(Math.PI, 5)} is all I can memorize.`);You should get the following output.
Terminal window PI is 3.141592653589793I find 3.14159 is all I can memorize.
We’ll cover more on functions in our Re-usable Functions tutorial. For now, just be aware that JavaScript let’s us create as many functions for as many use cases that we can imagine!
Math is for Numbers (not Strings)
We’ve been doing math with numbers. All the operators (+
, -
, *
, /
, and %
) are built to perform arithmetic with numeric values. But the plus operator (+
) works differently with strings - it performs concatenation.
In these steps, we’ll explore what happens when we’re not paying attention to our data types. Then, we’ll be deliberate about converting strings to numbers using parseInt()
and parseFloat()
.
-
Remember the rounding errors we encountered? They’re rare, but here’s another one:
159 - 194.1193
. This time, we’ll solve that using the.toFixed()
function from the prior tutorial in this series.basic-math.js // Another rounding error...floating = 159 - 194.1193; // produces -35.11930000000001answer = floating.toFixed(4); // the expected # digitsmessage = `Subtract 194.1193 from 159: ${answer}`;console.log(message);Subtracting a larger number from a smaller number gives us a negative number. You should see the following output.
Terminal window Subtract 194.1193 from 159: -35.1193 -
Now, let’s re-add the value we subtracted to see if we get the starting value of
159
.basic-math.js let original = answer + 194.1193;message = `Add ${answer} and 194.1193: ${original}`;console.log(message);Whoa! What happened?! Did you get this output?
Terminal window Add -35.1193 and 194.1193: -35.1193194.1193 -
We encountered a problem because the
answer
variable was holding a string instead of a number. That’s because.toFixed(4)
took the number inside thefloating
variable and created a string, which we stored intoanswer
.To get back to a number, we can use the
parseFloat()
function. Make the following fix to the code.basic-math.js let original = answer + 194.1193;let original = parseFloat(answer) + 194.1193;message = `Add ${answer} and 194.1193: ${original}`;console.log(message);Now we should see the correct output!
Terminal window Add -35.1193 and 194.1193: 159 -
We have two functions for converting strings to numbers:
parseFloat()
andparseInt()
. The first will convert to a floating-point or decimal value. The second will convert to a whole number. Add the following to your script.basic-math.js // Convert a string to a number.console.log('Includes the decimal portion:', parseFloat('3.75'));console.log('Exclude the decimal portion:', parseInt('3.75'));You should get this output.
Terminal window Includes the decimal portion: 3.75Exclude the decimal portion: 3 -
An interesting aspect of converting strings to numbers is that these functions will omit trailing characters that are not digits.
basic-math.js console.log('About PI:', parseFloat('3.14 is PI')); // Outputs 3.14But if there are leading characters that aren’t digits, then you get
NaN
(Not a Number).basic-math.js console.log('The price is:', parseFloat('$ 4.97')); -
So, the solution is to pay attention to the data types of the values you are working with.
basic-math.js // Remember how we can convert a number to a string?let total = 10 * 5.95; // quantity times unit pricelet money = `$ ${total.toFixed(2)}`;console.log('For math, I need numbers: ', total);console.log('I use strings to show as money: ', money);
Conclusion
In this tutorial, you’ve briefly gained some working knowledge of how to do math and seen the value of re-usable code (à la functions). You’ve explored some of the functions available in the Math
object for complex calculations and have seen how to deal with potential rounding errors when performing floating-point arithmetic. Lastly, you’ve seen the importance of knowing when you are working with numbers versus strings as well as how to convert string values into their numeric counterparts.
In the next tutorial, we’ll take a closer look at functions that allow us to manipulate strings.