ITP © Ron Poet Lecture 6 1 More on if
ITP © Ron Poet Lecture 6 2 Remembering Tests We often want to remember the result of a test, so that we can use it later on. We might work out if a year is a leap year or not. The formula is quite complicated. If we could remember the result of the test, we would not have to keep applying the complicated formula.
ITP © Ron Poet Lecture 6 3 boolean Data Type The boolean data type has two possible values, true and false. These are boolean literals. Any test is a boolean expression, with possible values true and false. We can store boolean values in boolean variables.
ITP © Ron Poet Lecture 6 4 Storing Test Results in Variables We can store our previous test results in boolean variables. boolean nightFeast = startTotalMins < 0; boolean itsRon = name.equals(“Ron”); They are either true or false. There are just examples, it would not be good style to actually do this in these cases.
ITP © Ron Poet Lecture 6 5 Using boolean Variables in Tests We can use these stored values in tests. As part of an if statement. if (nightFeast) startTotalMins = startTotalMins ; if (isRon) con.println(“Why, Hello Ron”); Using the tests later is often useful. But not in these simple examples.
ITP © Ron Poet Lecture 6 6 Leap Years The rules for deciding if a year is a leap year are complicated. Making it a useful example. A year is a leap year if: It is divisible by 4. But if it is divisible by 100 it is not a leap year. Unless it is also divisible by 400.
ITP © Ron Poet Lecture 6 7 Leap Year Calculation Let us try and calculate if a year is leap, storing the result in the boolean variable isLeapYear. We can use this stored value later on to calculate how many days there are in February of that year.
ITP © Ron Poet Lecture 6 8 Chaining if Statements Remember, make the most restrictive test first. Boolean isLeapYear; if (year % 400 == 0)// divisible by 400 isLeapYear = true; else if (year % 100 == 0) // divisible by 100 isLeapYear = false; else if (year % 4 == 0) // divisible by 4 isLeapYear = true; else isLeapYear = false;
ITP © Ron Poet Lecture 6 9 Nested if Statements We can go straight from the definition, leading to a less elegant solution. Boolean isLeaYear; if (year % 4 == 0) if (year % 100 == 0) if (year % 400 == 0) isLeapYear = true; else isLeapYear = false; else isLeapYear = true; else isLeapYear = false;
ITP © Ron Poet Lecture 6 10 Days in The Month Whichever approach we take, we now have a variable called isLeapYear that is either true or false. Now let us assume we have a String variable month which stores the 3 letter abbreviation of the month name. We want to calculate int daysInMonth.
ITP © Ron Poet Lecture 6 11 Twelve Tests The obvious solution is the rather long series of tests. if (month.equals(“Jan”)) daysInMonth = 31; else if (month.equals(“Feb”)) if (isLeapYear) daysInMonth = 29; else daysInMonth = 28; else if (month.equals(“Mar”)) daysInMonth = 31;...
ITP © Ron Poet Lecture 6 12 Reflection Note how we have stored the result of a test in a boolean variable. The boolean variable is then used in place of the test in an if statement. Note that things can get complicated and we have to keep track of which if the else parts belong to. Indentation is vital.
ITP © Ron Poet Lecture 6 13 Combining Tests The previous two examples have used multiple tests to calculate whether a year is leap and the days in a month. It would be convenient if we could combine tests to produce super-tests. Rather than using lots of if statements with simple tests.
ITP © Ron Poet Lecture 6 14 Boolean Operators Boolean operators combine tests to produce super-tests. These super-tests still have possible values of true or false. They can be used like any of the simpler tests. We can combine super-tests to produce even bigger tests, as far as we want.
ITP © Ron Poet Lecture 6 15 Test AND Test If we combine two tests with the AND operator then the result is only true if both the simple tests are true. If one test is false then the result is false, no matter what the result of the other test is. The Java notation for AND is &&.
ITP © Ron Poet Lecture 6 16 Test OR Test If we combine two tests with the OR operator then the result is true if only one of the simple tests is true. It is only false if both the simple tests are false. The Java notation for OR is ||. It has the lowest precedence of the boolean operators.
ITP © Ron Poet Lecture 6 17 NOT Test The NOT operator switches the value of the test. If the test were true then NOT test is false. If the test were false then NOT test is true. The Java notation for NOT is ! It has the highest precedence of the boolean operators.
ITP © Ron Poet Lecture 6 18 Days in the Month Again This makes the days in the month code easier. It fits on one page. Note that we combine the month test with OR. Only one test will ever be true!
ITP © Ron Poet Lecture 6 19 Days in the Month Code if (month.equals(“Jan”) || month.equals(“Mar”) || month.equals(“May”) || month.equals(“Jul”) || month.equals(“Aug”) || month.equals(“Oct”) || month.equals(“Dec”)) daysInMonth = 31; else if (month.equals(“Apr”) || month.equals(“Jun”) || month.equals(“Sep”) || month.equals(“Nov”)) daysInMonth = 30; else// must be Feb if (isLeapYear) daysInMonth = 29; else daysInMonth = 28;
ITP © Ron Poet Lecture 6 20 Leap Years Again The leap year code is also complicated. We must make sure we have the right combinations of AND and OR. Use test data. Year = 3, 4, 100, 400 covers all the possibilities.
ITP © Ron Poet Lecture 6 21 Leap Year Code if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) isLeapYear = true; else isLeapYear = false;
ITP © Ron Poet Lecture 6 22 Testing in a Range Suppose we want a test that is true if an integer x is between 37 and 39. We must make two tests. x >= 37, bigger than the lower value. x <= 39, smaller than the higher value. Join them with AND, both tests must be true. if (x >= 37 && x <= 39).
ITP © Ron Poet Lecture 6 23 Alphabetical Order We might want to test two strings to see which one comes first in the alphabet. Use compareTo rather than equals. a.compareTo(b) returns an int. If the value < 0 then a comes before b. If the value > 0 then a comes after b. If the value == 0 then a and b are equal.
ITP © Ron Poet Lecture 6 24 Dangling else If we have two if s but only one else. The else belongs to the nearest if. if (test1) if (test2) // else belongs to this one statement; else statement; Unless that is not possible because of {}.
ITP © Ron Poet Lecture 6 25 Dangling else and {} if (test1) // else belongs to this if { if (test2) // statement; } else statement;
ITP © Ron Poet Lecture 6 26 doubles Are Not Stored Exactly Real numbers ( double ) are not normally stored exactly. They are stored very accurately, to around 17 significant figures. A variable that we expect to hold the value 3.0 might actually hold This is good enough for most purposes. int s are stored exactly.
ITP © Ron Poet Lecture 6 27 Comparing doubles If we compare a variable x with the value 3.0 then the result might be false because x actually contained We should not write if (x == 3.0) We should instead subtract 3.0 from x and see if the number is very small.
ITP © Ron Poet Lecture 6 28 Close Enough If x is close enough to 3.0, then x – 3.0 will be a small number, either positive or negative. We should take the absolute value of x – 3.0 which is always positive. if (x > 3.0) absxmin3 = x – 3.0; else absxmin3 = x; It is better to use java.lang.Math.abs(x – 3.0).
ITP © Ron Poet Lecture 6 29 Close Enough (2) A typical small value is 1.0e-10. So the test to see if x is close enough to 3.0 would be if (java.lang.Math.abs(x – 3.0) < 1.0e-10)