A question with only two possible answers
Every decision a program makes comes down to a question that is either true or false: Is the balance negative? Is the score at least 50? Is this number even? Java stores the answer to such a question in the type boolean, which has exactly two values, true and false. An expression that evaluates to one of them is a Boolean expression.
In Topic 2.1 you saw that selection and repetition are controlled by a true or false decision. This topic is about how to write those decisions. The simplest Boolean expressions are built from two values and a relational operator.
The six relational operators
| Operator | Meaning | Example | Value if a is 7 and b is 4 |
|---|---|---|---|
== |
equal to | a == b |
false |
!= |
not equal to | a != b |
true |
< |
less than | a < b |
false |
> |
greater than | a > b |
true |
<= |
less than or equal to | a <= b |
false |
>= |
greater than or equal to | a >= b |
true |
The first two, == and !=, test whether values are the same. With primitive types such as int, double and boolean, they compare the actual values. With reference types (objects) they compare the object references, which you will meet in Topic 2.6. The other four compare the size of numeric values only.
An expression involving a relational operator always evaluates to a boolean value. It never gives a number or a string. This is why you can store it in a boolean variable or place it where Java expects a condition.
public class Relational {
public static void main(String[] args) {
int a = 7;
int b = 4;
System.out.println(a == b);
System.out.println(a != b);
System.out.println(a > b);
System.out.println(a <= b);
System.out.println(a % b == 3);
}
}
Output:
false
true
true
false
true
The last line shows that arithmetic happens first: a % b is the remainder of 7 divided by 4, which is 3, and then 3 == 3 is true.
Precedence: arithmetic first, comparison last
An expression such as a + b * 2 > c - 1 contains arithmetic operators and a relational operator. Java evaluates the arithmetic first, using the usual precedence (multiplication, division and remainder before addition and subtraction), and then applies the relational operator to the two results. You can add brackets to make the order obvious, but you do not need them here.
Always evaluate both sides to a single value, then compare.
Integer division inside a comparison
Because int division discards the fractional part, comparisons that involve division need care. Suppose we want to know whether the average of two scores is above 50, and the scores are 50 and 51. The true average is 50.5, so the answer should be true.
int a = 50;
int b = 51;
boolean wrong = (a + b) / 2 > 50;
boolean right = (a + b) / 2.0 > 50;
System.out.println(wrong + " " + right);
Output:
false true
In wrong, both operands of / are int, so 101 / 2 is the int 50, and 50 > 50 is false. In right, dividing by 2.0 produces a double, 50.5, and 50.5 > 50 is true. The comparison is only as good as the numbers that go into it.
Round-off error and doubles
A double stores most decimal values only approximately. If an expression would give a value that is more precise than the allotted memory can hold, the result is rounded, which is called round-off error. This means == can disappoint you when it compares computed doubles.
double sum = 0.1 + 0.2;
System.out.println(sum == 0.3);
System.out.println(Math.abs(sum - 0.3) < 0.000001);
Output:
false
true
Although 0.1 + 0.2 looks like 0.3 on paper, the stored result is a tiny amount different, so the first comparison is false. A better test asks whether the two values are close enough: the absolute difference, Math.abs(sum - 0.3), is smaller than a small tolerance. Where the problem allows it, use int values to avoid the issue altogether.
Boolean variables
Because a relational expression has a boolean value, you can assign it to a boolean variable and use the variable later:
int n = 14;
boolean isEven = n % 2 == 0;
boolean isBig = n > 20;
System.out.println(isEven + " " + isBig);
Output:
true false
The assignment operator = has the lowest precedence, so Java evaluates n % 2 == 0 first and then stores the result. Choosing names such as isEven makes later conditions read like English.
Two errors the compiler catches
Assignment instead of comparison. = stores a value; == compares. For int values, x = 5 is an assignment expression whose value is an int, and a condition must be boolean, so the compiler rejects it.
int x = 5;
boolean r = (x = 5);
This does not compile: Java reports that an int cannot be converted to boolean.
Chained comparisons. Mathematics lets you write 3 < x < 9. Java does not. The expression 3 < x < 9 is evaluated left to right as (3 < x) < 9, which tries to compare a boolean with an int and does not compile. To express “x is between 3 and 9” you need two comparisons joined by a logical operator, covered in Topic 2.5.
int x = 5;
boolean r = 3 < x < 9;
Worked example 1: evaluating expressions
Question. Let a = 6, b = 4, c = 10. Evaluate each expression and say what its type is.
a + b == cc / b > 2c % a != b(a + b) * 2 <= c + ac / a == 1.5
Solution. Work out both sides, then compare.
| Expression | Left side | Right side | Result |
|---|---|---|---|
a + b == c |
6 + 4 = 10 | 10 | 10 == 10 is true |
c / b > 2 |
10 / 4 = 2 (int division) | 2 | 2 > 2 is false |
c % a != b |
10 % 6 = 4 | 4 | 4 != 4 is false |
(a + b) * 2 <= c + a |
10 * 2 = 20 | 10 + 6 = 16 | 20 <= 16 is false |
c / a == 1.5 |
10 / 6 = 1 (int division), compared as 1.0 | 1.5 | 1.0 == 1.5 is false |
All five are of type boolean. Check: in item 2 the exact quotient is 2.5, which is greater than 2, but both operands are int, so the quotient is truncated to 2. Remembering which divisions are integer divisions is the commonest source of wrong answers. In item 5, Java converts the int 1 to the double 1.0 before comparing.
Worked example 2: from English to Java
Question. Write a Boolean expression for each statement and evaluate it for the given values.
- A person is old enough to vote:
ageis at least 18 (age = 17). - A number leaves remainder 2 when divided by 5 (
n = 37). - The total
tis not zero (t = 0). - The average of
pandqis greater than 50 (p = 50,q = 51). - The year
yis a multiple of 4 (y = 2026).
Solution.
public class FromEnglish {
public static void main(String[] args) {
int age = 17, n = 37, t = 0, p = 50, q = 51, y = 2026;
System.out.println(age >= 18);
System.out.println(n % 5 == 2);
System.out.println(t != 0);
System.out.println((p + q) / 2.0 > 50);
System.out.println(y % 4 == 0);
}
}
Output:
false
true
false
true
false
Reasoning.
- “At least 18” means 18 or more, so the operator is
>=, not>. 17 >= 18 is false. - “Remainder 2 when divided by 5” is
n % 5 == 2. 37 = 7 × 5 + 2, so the remainder is 2 and the result is true. - “Not zero” is
!=. 0 != 0 is false. - The average needs a
doubledivision (2.0) so that 50.5 is not truncated to 50. 50.5 > 50 is true. - “Multiple of 4” means the remainder after dividing by 4 is 0. 2026 = 506 × 4 + 2, the remainder is 2, so the result is false.
Check on word choice. “At least” means >=, “at most” means <=, “more than” means >, “fewer than” means <, “exactly” or “the same as” means ==, and “different from” means !=. Reading the boundary word carefully is worth a mark on almost every Boolean-expression question.
Common misconceptions
- “= and == are interchangeable.”
=stores a value,==compares two values. They are different operators with different results. - “A relational expression can have a numeric result.” It cannot.
a > bis true or false, never a number. - “3 < x < 9 means x is between 3 and 9.” It is a compile-time error in Java. Use two comparisons and a logical operator.
- “At least” and “more than” are the same.“ “At least 18” is
>= 18; “more than 18” is> 18. They differ when the value is exactly 18. - “The comparison is exact when numbers look exact.” Integer division truncates, and doubles carry round-off error, so what you see on paper is not always what the computer compares.
- “You can use < with Strings.” The relational operators
<,>,<=and>=are for numeric values only. - “Precedence goes left to right across everything.” Arithmetic is evaluated before the relational operator, regardless of where the comparison sits.
Where this leads
Boolean expressions are the conditions in every if statement and loop. In Topic 2.3 you will use them to choose between two paths. In Topic 2.5 you will combine them with &&, || and !. Practise now with the practice questions, recap with the revision notes and tick off the checklist. Then read the Topic 2.3 study guide on if statements. If the idea of selection feels hazy, revisit the Topic 2.1 study guide.
Quick questions
What is the difference between = and ==?
A single = is the assignment operator: it stores a value in a variable. A double == is the comparison operator: it asks whether two values are equal and produces true or false. For int and double values, writing = inside a condition is a compile-time error.
Why does 3 < x < 9 not compile?
Java evaluates it left to right. 3 < x gives a boolean, and then the program tries to compare that boolean with 9 using <, which is not allowed. You need two comparisons joined by a logical operator, which is Topic 2.5.
Can I use < and > with Strings?
No. The relational operators <, >, <= and >= work with numeric values only. Strings are compared with the compareTo and equals methods, and == on objects compares references (Topic 2.6).
Is it safe to compare two doubles with ==?
Not when they are the result of arithmetic. Doubles have round-off error, so 0.1 + 0.2 is not exactly 0.3. Compare the difference with a small tolerance instead, or use int values when you can.