Doing math
Problem
The bill at the table
You ordered three coffees at €2.50 and two croissants at €1.50. You pay with a €20 bill. How much is the bill, and how much change should you get?
You can do it in your head. But the register at the café does this math hundreds of times a day, with different prices and quantities. The program has to do the math by itself.
The idea
The arithmetic operators
You do math the way you would on paper: + adds, - subtracts, * multiplies, / divides. These signs are called operators.
const coffee = 2.5;const croissant = 1.5;const total = 3 * coffee + 2 * croissant;const change = 20 - total;console.log("Total: €" + total);console.log("Change: €" + change);Total: €10.5Change: €9.5The order is the same as in math: first * and /, then + and -. That is why 3 * coffee + 2 * croissant is 7.5 + 3. If you want a different order, you add parentheses: (2 + 3) * 4 is 20.
There is a fifth operator too, %. The next idea is about it.
More precisely, if you are curious
- Operators with the same precedence are evaluated left to right:
20 - 5 - 3is 12, not 18. -in front of a number makes it negative:-total.
- With text,
+does not add, it glues. Once there is text on the left, everything after it is glued on as text. That is the trap in the next card.
Try it
Concert tickets
Three tickets at €8 and a €5 order fee.
What will the program print?
const tickets = 3;const fee = 5;console.log("Total: " + tickets * 8 + fee);* is done first: tickets * 8 is 24. Then left to right: "Total: " + 24 is the text "Total: 24", and 5 is glued onto it. To get 29, the math has to be in parentheses: "Total: " + (tickets * 8 + fee).Problem
2.25 hours instead of 2 h 15 min
The movie is 135 minutes long. You want to show it as hours and minutes: 2 h 15 min. The first try:
const minutes = 135;const hours = minutes / 60;console.log(hours + " h");2.25 hIn JavaScript, / always gives a decimal result, even when both numbers are whole: 6 / 3 is 2, and 17 / 3 is 5.666666666666667. But here you need two whole hours and the minutes that are left. How do you get only the whole part?
The idea
The whole part and the remainder
Math.trunc(...) cuts off the decimal part of a number: Math.trunc(2.25) is 2. So Math.trunc(135 / 60) gives the whole hours, and Math.trunc(17 / 3) is 5. This is called integer division. Math is a set of ready-made calculations. There are more of them at the end of the lesson.
Here it is step by step, with the sum of three grades:
const math = 5;const physics = 6;const english = 6;const whole = Math.trunc((math + physics + english) / 3);console.log("Whole part: " + whole);Step by step, in words
- Three grades: 5, 6, 6.
- First the parentheses: 5 + 6 + 6 = 17.
- 17 / 3 is 5.667…, and Math.trunc keeps only the whole part: how many whole groups of 3 are in 17? 5.
- The remainder 2 (that is 17 % 3) is cut off. The result is the whole number 5.
- 5 is stored in whole.
- It prints "Whole part: 5". The decimal part (5.67) is not in the result.
What is cut off is not completely lost. The % operator gives the remainder of the division: 17 % 3 is 2, because 17 = 5 · 3 + 2.
Together the two split an amount into whole parts and a remainder. The movie is 135 minutes:
const minutes = 135;const hours = Math.trunc(minutes / 60);const rest = minutes % 60;console.log(hours + " h " + rest + " min");2 h 15 minYou will need % often. A number is even if n % 2 is 0. The last digit of a number is n % 10.
More precisely, if you are curious
- With negative numbers
Math.trunccuts off toward zero, and the remainder has the sign of the dividend.%also works with decimal numbers:
console.log(Math.trunc(-7 / 2));console.log(-7 % 2);console.log(7.5 % 2);-3-11.5- Division by 0 does not stop the program:
5 / 0givesInfinity, and0 / 0and5 % 0giveNaN("not a number").
Try it
Bottles in cases
A case holds 6 bottles. You have 17.
What will the program print?
const bottles = 17;const perCase = 6;console.log(Math.trunc(bottles / perCase) + " cases");console.log(bottles % perCase + " left over");Math.trunc(17 / 6) is 2 whole cases (12 bottles), and 17 % 6 is the remainder: 5 bottles that do not fill a case.
The idea
Converting between types
In JavaScript numbers are one type, number. There are no separate whole and decimal types to convert between: / gives a decimal result, as you saw. You make a whole number from a decimal one with Math:
const total = 5 + 6 + 6;const average = total / 3;console.log(average);console.log(average.toFixed(2));const whole = Math.trunc(9.99);console.log(whole);5.6666666666666675.679Math.trunc(9.99)is 9: it cuts off the decimal part, it does not round;Math.round(9.99)is 10: it rounds to the nearest whole number;Math.floor(9.99)is 9 andMath.ceil(9.01)is 10: they round down and up.
JavaScript does have conversion between types from text to a number: that is Number(...) from the lesson on input.
More precisely, if you are curious
- Every character has a code, a number in the character table.
charCodeAt(0)gives the code of the first character, andString.fromCharCodemakes a character from a code:
console.log("A".charCodeAt(0));console.log(String.fromCharCode(66));const maxInt = 2147483647;console.log(maxInt + 1);console.log(9007199254740992 + 1);65B21474836489007199254740992- In Java and C#,
intgoes up to 2,147,483,647, and one more "wraps around" to a negative number. In JavaScript 2147483647 + 1 is simply 2147483648. The limit is somewhere else: whole numbers are exact up to 9,007,199,254,740,991, and after that they lose precision (the last line). For bigger whole numbers there isBigInt.
Try it
Find the bug
The electricity bill is €125, split between three roommates. The program says each person pays €41.00, but it should be €41.67. Which line is the bug on?
Pick the line with the bug.
bill / people is 41.666…, but Math.trunc cuts off the decimal part and 41 is left. toFixed(2) then shows it as 41.00. The fix is to not cut anything off: const share = bill / people;.The idea
Shorthand: += and ++
You often change a value based on itself: the card balance goes down with every purchase, a counter goes up by one. There is a short way to write this:
let balance = 20;let purchases = 0;balance -= 4.5;purchases++;balance -= 3.5;purchases++;console.log(purchases + " purchases, €" + balance + " left");2 purchases, €12 left| You write | It means |
|---|---|
balance -= 4.5; |
balance = balance - 4.5; |
total += price; |
total = total + price; |
x *= 2;, x /= 2;, x %= 2; |
the same with *, / and % |
purchases++; |
purchases = purchases + 1; |
seats--; |
seats = seats - 1; |
+= works with text too: message += "!"; glues an exclamation mark onto the end.
More precisely, if you are curious
++ can also go in front of the variable. On its own line there is no difference. Inside an expression there is: a++ gives the old value and then increases it, ++a increases it first and gives the new value.
let a = 5;const b = a++;const c = ++a;console.log(a + " " + b + " " + c);7 5 7Code like this is hard to read. Write ++ and -- on their own line.
The idea
Math: roots, powers, rounding
A pizza place sells a 30 cm pizza for the same price as two 20 cm pizzas. Which is more? The area of a circle is π · r². For the power and for π there is something ready in Math: you write the name and the numbers in parentheses. Math is always available, without loading it. These are functions, ready-made pieces of code. You will write your own in the "Functions" module.
const big = Math.PI * Math.pow(15, 2);const small = 2 * Math.PI * Math.pow(10, 2);console.log(`One 30 cm pizza: ${big.toFixed(1)} sq cm`);console.log(`Two 20 cm pizzas: ${small.toFixed(1)} sq cm`);console.log(Math.sqrt(144));console.log(Math.abs(-7.5));One 30 cm pizza: 706.9 sq cmTwo 20 cm pizzas: 628.3 sq cm127.5One big pizza is more than two small ones.
| You write | What it gives |
|---|---|
Math.sqrt(x) |
the square root |
Math.pow(x, n) or x ** n |
x to the power n |
Math.abs(x) |
the absolute value (without the sign) |
Math.round(x) |
rounding to a whole number |
Math.trunc(x) |
the whole part, without rounding |
Math.PI |
the number π, 3.14159… |
In JavaScript Math.sqrt(144) is simply 12: the number is the same type, whole or decimal.
More precisely, if you are curious
- Rounding 2.5: the languages give different results.
console.log(Math.round(2.5));console.log(Math.round(3.5));console.log(Math.round(-2.5));console.log(Math.round(5.678 * 100) / 100);34-25.68Math.roundrounds "the half" up, toward the bigger number: 2.5 becomes 3, and -2.5 becomes -2. For two digits after the decimal point you multiply by 100, round and divide by 100. If it is only for printing,toFixed(2)is easier.
- toFixed does not follow the computer's language settings: a point stays a point everywhere.
Exercise
Let the program do the math
Solve the tasks in your editor. Each number in the input is on a separate line.
1. Average of three numbers. Read three whole numbers and print their average with two digits after the decimal point. Here you need decimal division.
566Average: 5.672. Seconds into hours. Read a number of seconds and split it into hours, minutes and seconds. Hint: an hour has 3600 seconds, and % gives what is left.
37251 h 2 min 5 s3. Volume of a sphere. Read the radius and print the volume: V = 4/3 · π · r³. Here 4 / 3 is 1.333…, as it should be.
10Volume: 4188.79 cubic cm4. Celsius to Fahrenheit. F = C · 9 / 5 + 32. Read the temperature in degrees Celsius.
3737.0 °C = 98.6 °FMore tasks
- Inches to centimeters. One inch is 2.54 cm. For 12 inches:
30.48 cm. - Area of a rectangle. Read the length and the width, and print the area (length · width).
- Area of a square. Read the side and print the area. Do it once with
*and once withMath.pow. - Radians to degrees. Degrees = radians · 180 / π. For 3.14159:
180.00°. - Hours to seconds. Read a number of hours and print how many seconds that is. For 2 hours: 7200.
- A character's code. Read a character and print its code. For
A: 65. You get the first character of the text you read with(await ask(""))[0]. You will see what this means in the lesson on text.
Test