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.
double coffee = 2.5;double croissant = 1.5;double total = 3 * coffee + 2 * croissant;double change = 20 - total;System.out.println("Total: €" + total);System.out.println("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?
int tickets = 3;int fee = 5;System.out.println("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
An average grade of 5, not 5.67
You have grades 5, 6 and 6. The average is 17 / 3 = 5.67. The program says something else:
int math = 5;int physics = 6;int english = 6;double average = (math + physics + english) / 3;System.out.println("Average grade: " + average);Average grade: 5.0You store the result in a double, and the decimal part is still missing. Where did it go?
The idea
Whole divided by whole gives whole
When both sides of / are int, the division is integer division: the result is a whole number, and the decimal part is cut off. 17 / 3 is 5. Only after that is the 5 stored in the double, where it becomes 5.0.
Here is the average grade from the last card, step by step:
int math = 5;int physics = 6;int english = 6;double average = (math + physics + english) / 3;System.out.println("Average grade: " + average);Step by step, in words
- Three grades, each in an int: 5, 6, 6.
- First the parentheses: 5 + 6 + 6 = 17. The sum is an int too.
- 17 / 3: both sides are int. 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.
- Only now is 5 stored in double average, where it becomes 5.0.
- It prints "Average grade: 5.0". 5.67 does not show up anywhere.
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:
int minutes = 135;int hours = minutes / 60;int rest = minutes % 60;System.out.println(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 the result is cut off toward zero, and the remainder has the sign of the dividend.
%also works with decimal numbers:
System.out.println(-7 / 2);System.out.println(-7 % 2);System.out.println(7.5 % 2);-3-11.5- A whole number divided by 0 stops the program with an error:
ArithmeticException: / by zero. Withdoublethere is no error:5.0 / 0gives infinity, and0.0 / 0givesNaN("not a number").
Try it
Bottles in cases
A case holds 6 bottles. You have 17.
What will the program print?
int bottles = 17;int perCase = 6;System.out.println(bottles / perCase + " cases");System.out.println(bottles % perCase + " left over");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
For the division to give a decimal result, at least one side has to be a double. If you have an int, you convert it: you write the type in parentheses in front of the value. This is called a cast.
int sum = 5 + 6 + 6;double average = (double) sum / 3;System.out.println(average);System.out.printf("%.2f%n", average);int whole = (int) 9.99;System.out.println(whole);5.6666666666666675.679(double) sum turns 17 into 17.0, and then the division gives a decimal result. If the number is written in the code, it is enough to make it a decimal: sum / 3.0.
The other way, from double to int, cuts off the decimal part: (int) 9.99 is 9, not 10. That is why the compiler does not do it by itself: if you write int whole = 9.99;, the program does not compile. From int to double nothing is lost, and the conversion happens by itself: double price = 10; is 10.0.
More precisely, if you are curious
- A cast goes from a number to a number. You already turn text into a number with
Integer.parseInt: that is something else. - A character (
char) is actually stored as a number, its code. That is why it converts tointand back:
System.out.println((int) 'A');System.out.println((char) 66);int max = 2147483647;System.out.println(max + 1);65B-2147483648- The third line is a surprise:
intgoes up to 2,147,483,647. One more does not give an error. It "wraps around" to the smallest negative number. For bigger numbers there islong.
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.
125 / 3 is integer division and gives 41. The cast comes only after that and turns 41 into 41.0. The fix is to cast before the division: (double) 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:
double balance = 20;int purchases = 0;balance -= 4.5;purchases++;balance -= 3.5;purchases++;System.out.println(purchases + " purchases, €" + balance + " left");2 purchases, €12.0 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.
int a = 5;int b = a++;int c = ++a;System.out.println(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. These are methods, ready-made pieces of code. You will write your own in the "Methods" module.
double big = Math.PI * Math.pow(15, 2);double small = 2 * Math.PI * Math.pow(10, 2);System.out.printf("One 30 cm pizza: %.1f sq cm%n", big);System.out.printf("Two 20 cm pizzas: %.1f sq cm%n", small);System.out.println(Math.sqrt(144));System.out.println(Math.abs(-7.5));One 30 cm pizza: 706.9 sq cmTwo 20 cm pizzas: 628.3 sq cm12.07.5One big pizza is more than two small ones.
| You write | What it gives |
|---|---|
Math.sqrt(x) |
the square root |
Math.pow(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.PI |
the number π, 3.14159… |
The square root and the power return a double, even when the result is a whole number (that is why you see 12.0). If you need an int, convert it: (int) Math.sqrt(144).
More precisely, if you are curious
- Rounding 2.5: Java and C# give different results.
System.out.println(Math.round(2.5));System.out.println(Math.round(3.5));System.out.println(Math.round(5.678 * 100) / 100.0);345.68Math.roundrounds "the half" up and returns along, not anint. For two digits after the decimal point you multiply by 100, round and divide by100.0. If it is only for printing,printf("%.2f")is easier.
- printf follows the computer's language settings. On a computer with Bulgarian settings you will see
706,9, not706.9.
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. Watch out for the 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³. Think about what 4 / 3 is before you write it like that.
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 within.nextLine().charAt(0). You will see what this means in the lesson on text.
Test